Java Forum / General / November 2005
Easy way to create a list of strings?
brightoceanlight@hotmail.com - 08 Nov 2005 13:32 GMT I'm trying to create a HashSet of Strings but I don't want to have to add each string to the HashSet. There is a constructor for HashSet that allows you to give it a Collection. But how can I create a Collection of String other than having to add each string? Can I just
HashSet hs = new HashSet("String1", "String2", "String3", "String4");
?
chris_k - 08 Nov 2005 13:40 GMT Hi,
> But how can I create a > Collection of String other than having to add each string? You may use Arrays.asList(...) if suitable for your needs.
HTH, chris
zero - 08 Nov 2005 13:43 GMT brightoceanlight@hotmail.com wrote in news:1131456730.614859.323070 @f14g2000cwb.googlegroups.com:
> I'm trying to create a HashSet of Strings but I don't want to have to > add each string to the HashSet. There is a constructor for HashSet [quoted text clipped - 4 lines] > > ? If the Strings are in an array it's easy:
String[] myStrings = {"String1", "String2", "String3", "String4"}; HashSet stringSet = new HashSet(Arrays.asList(myStrings));
Or, you can use an enhanced for loop:
String[] myStrings = {"String1", "String2", "String3", "String4"}; HashSet stringSet = new HashSet(); for(String s : myStrings) HashSet.add(s);
Note: in JDK 1.5 you should use generic collections to avoid warnings:
String[] myStrings = {"String1", "String2", "String3", "String4"}; HashSet<String> stringSet = new HashSet<String>(Arrays.asList(myStrings));
Roedy Green - 08 Nov 2005 14:28 GMT >HashSet hs = new HashSet("String1", "String2", "String3", "String4"); Look at the JavaDoc.
the HashSet constructor will eat a Collection.
So you problem is how to turn your list of strings in to a Collection.
Well you can start by turning it into an array
String[] twine = new String[]{ "String1", "String2", "String3", "String4" };
How do we get an array turned into a Collection? Check out http://mindprod.com/jgloss/array.html
There's the recipe, how to convert an array to a Collection and back.
// Convert an array to a List: String[] animals = { "bear", "cougar", "wolverine" }; List list = Arrays.asList( animals ) );
// A List can then be fed to the constructor or addAll method // of many Collections: Collection<String> h = new HashSet<String>( list );
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Thomas G. Marshall - 09 Nov 2005 18:01 GMT Roedy Green coughed up:
...[rip]...
> // Convert an array to a List: > String[] animals = { "bear", "cougar", "wolverine" }; > List list = Arrays.asList( animals ) ); I always prefer the anon. Multi lined to defeat line breakage in usenet:
List list = Arrays.asList( new String[] {"bear", "cougar", "wolverine"} );
Seems nifty enough to me.
 Signature Puzzle: You are given a deck of cards all face down except for 10 cards mixed in which are face up. If you are in a pitch black room, how do you divide the deck into two piles (may be uneven) that each contain the same number of face-up cards? Answer (rot13): Sebz naljurer va gur qrpx, qrny bhg gra pneqf naq syvc gurz bire.
Roedy Green - 10 Nov 2005 01:10 GMT On Wed, 09 Nov 2005 18:01:38 GMT, "Thomas G. Marshall" <tgm2tothe10thpower@replacetextwithnumber.hotmail.com> coughed this wad of congealed sputum up from his tubercular lungs:
>> // Convert an array to a List: >> String[] animals = { "bear", "cougar", "wolverine" }; [quoted text clipped - 7 lines] > >Seems nifty enough to me. In the Java glossary examples, I tend to avoid contractions. I want to make it as clear as possible to newbies what is happening.
Along those lines, one form I particularly avoid is: new Xxxx().method(); which really seems to throw them.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Thomas G. Marshall - 10 Nov 2005 04:29 GMT Roedy Green coughed up:
> On Wed, 09 Nov 2005 18:01:38 GMT, "Thomas G. Marshall" > <tgm2tothe10thpower@replacetextwithnumber.hotmail.com> coughed this > wad of congealed sputum up from his tubercular lungs: LOL
>>> // Convert an array to a List: >>> String[] animals = { "bear", "cougar", "wolverine" }; [quoted text clipped - 14 lines] > new Xxxx().method(); > which really seems to throw them. IMO it's important for newbies to get a handle on anonymous classes/arrays as soon as possible, because their syntax is so odd seeming and they will be seeing a great deal of them.
 Signature "Realtor" and "realty" are pronounced "reel'-tor" and "reel'-tee", *not* "reel'-a-tor" and "reel'-i-tee" !!!! If you pronounce them with the extra syllable, you will sound like a complete idiot.
Mike Schilling - 10 Nov 2005 15:38 GMT > "Realtor" and "realty" are pronounced "reel'-tor" and > "reel'-tee", *not* "reel'-a-tor" and "reel'-i-tee" !!!! > If you pronounce them with the extra syllable, you will > sound like a complete idiot. At least people will know you're not a realtor.
Thomas G. Marshall - 10 Nov 2005 17:35 GMT Mike Schilling coughed up:
>> "Realtor" and "realty" are pronounced "reel'-tor" and >> "reel'-tee", *not* "reel'-a-tor" and "reel'-i-tee" !!!! >> If you pronounce them with the extra syllable, you will >> sound like a complete idiot. > > At least people will know you're not a realtor. Nope. I actually heard a *COMERCIAL* on the radio saying it that way, albeit only once. Hopefully once it was aired, somebody [the voice over] either was fired, or had a severe talking to.
 Signature Forgetthesong,I'dratherhavethefrontallobotomy...
Thomas G. Marshall - 10 Nov 2005 17:37 GMT Thomas G. Marshall coughed up:
> Mike Schilling coughed up: >>> "Realtor" and "realty" are pronounced "reel'-tor" and [quoted text clipped - 5 lines] > > Nope. I actually heard a *COMERCIAL* ...but then bad spellers at least could have a career in radio...
> on the radio saying it that way, > albeit only once. Hopefully once it was aired, somebody [the voice over] > either was fired, or had a severe talking to.
 Signature Forgetthesong,I'dratherhavethefrontallobotomy...
Chris Uppal - 08 Nov 2005 16:00 GMT > I'm trying to create a HashSet of Strings but I don't want to have to > add each string to the HashSet. There is a constructor for HashSet > that allows you to give it a Collection. But how can I create a > Collection of String other than having to add each string? If you are willing to define a helper method, and can stomach the abuse of the language feature (and are using 1.5 so you've /got/ the language feature to abuse ;-), then you could try (untested):
public HashSet makeHashSet(String... args) { return new HashSet(Arrays.asList(args)); }
which (if I've got the syntax right) can be called as:
makeHashSet("String1", "String2", "String3", "String4");
(There's an extra hoop or two to be jumped through in order to persuade the type-system to accept it, but that's a different story...)
-- chris
Mike Schilling - 09 Nov 2005 02:17 GMT >> I'm trying to create a HashSet of Strings but I don't want to have to >> add each string to the HashSet. There is a constructor for HashSet [quoted text clipped - 15 lines] > > makeHashSet("String1", "String2", "String3", "String4"); Is that an abuse? If, so I suppose the "right" way to do this is
HashSet makeHashSet(String... args) { HashSet hs = new HashSet<String>; for (String s : args) hs.add(s); return hs; }
Is that really better?
Thomas Hawtin - 09 Nov 2005 03:14 GMT > Is that an abuse? If, so I suppose the "right" way to do this is > > HashSet makeHashSet(String... args) ^<String>
> { > HashSet hs = new HashSet<String>; ^<String>
> for (String s : args) > hs.add(s); > return hs; > } > > Is that really better? No. Adding a single, small allocation was probably not a problem. Arrays.asList gives tighter object code and can allow HashSet to choose a capacity appropriate for the number of elements.
Another way to do it, which you might consider an abuse, is more suitable for maps...
Map<String, String> map = new HashMapBuilder<String,String>() .put("fred", "Fred") .put("jim", "Jim") .put("sheila", "Sheila") .put("mcdoughnut", "McDoughnut") .create();
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Chris Uppal - 09 Nov 2005 11:04 GMT > Map<String, String> map = new HashMapBuilder<String,String>() > .put("fred", "Fred") > .put("jim", "Jim") > .put("sheila", "Sheila") > .put("mcdoughnut", "McDoughnut") > .create(); Perhaps more flexibly:
Map<String, String> map = new HashMap<String, String>(); MapStuffer.for(map) .put("fred", "Fred") .put("jim", "Jim") .put("sheila", "Sheila") .put("mcdoughnut", "McDoughnut");
So that the choice of Map type is left up to the user, and the job of MapStuffer is /only/ to be an adaptor allowing the use of the chained-send idiom. If you like that idiom (I don't, myself, but it's a matter of taste) then a handful of such helpers might make a worthwhile addition to your toolkit. Hmm, maybe XxxStuffer isn't such a good name since you might want to use the adaptors for removing items too...
-- chris
Chris Uppal - 09 Nov 2005 11:53 GMT I wrote:
> So that the choice of Map type is left up to the user, and the job of > MapStuffer is /only/ to be an adaptor allowing the use of the chained-send > idiom. Dunno why, but I got interested enough to write some code. Use like:
List<String> list = new ArrayList<String>(); Stuffer.stuffing(list) .add("one") .add("two") ... .add("sixteen");
(which works for Sets too) or:
Map<Integer, String> map = new HashMap<Integer, String>(); Stuffer.stuffing(map) .put(1, "one") .put(2, "two") ... .put(16, "sixteen");
Irritating that "for" is a reserved word...
BTW, I also wrote:
> If you like that idiom (I don't, myself, but it's a matter of taste) I quite like this Stuffer, so I've changed my mind. What I /actually/ dislike is not the idiom itself, which is fine -- even quite elegant, but classes which have warped designs just in order to support the idiom. With that insight (if you can call it that), I'll also withdraw my rider that it is just "a matter of taste".
-- chris
====== code =======
import java.util.*;
public class Stuffer { public static class ForMaps<X, Y> { private final Map<X, Y> m_map;
ForMaps(Map<X, Y> map) { m_map = map; }
public ForMaps<X, Y> put(X x, Y y) { m_map.put(x, y); return this; } }
public static class ForCollections<X> { private final Collection<X> m_collection;
ForCollections(Collection<X> collection) { m_collection = collection; }
public ForCollections<X> add(X x) { m_collection.add(x); return this; } }
public static <X, Y> ForMaps<X, Y> stuffing(Map<X, Y> map) { return new ForMaps<X, Y>(map); }
public static <X> ForCollections<X> stuffing(Collection<X> collection) { return new ForCollections<X>(collection); } } ==================
Thomas Hawtin - 09 Nov 2005 12:04 GMT >> Map<String, String> map = new HashMapBuilder<String,String>() >> .put("fred", "Fred") [quoted text clipped - 15 lines] > MapStuffer is /only/ to be an adaptor allowing the use of the chained-send > idiom. If you like that idiom (I don't, myself, but it's a matter of taste) I didn't like having to assign the reference to a variable. Perhaps something like:
Map<String, String> map = Maps.builder(new HashMap<String, String>()) ...
Or the full hog:
HashMap<String, String> map = new Builder<String, String, HashMap<String, String>>( new HashMap<String, String>() ) .put("fred", "Fred") .put("jim", "Jim") .put("sheila", "Sheila") .put("mcdoughnut", "McDoughnut") .get();
public static final class Builder<K, V, I extends Map<K, V>> { private final I map; private Builder(I map) { this.map = map; } public Builder<K, V, I> put(K key, V value) { map.put(key, value); return this; } public I get() { return map; }
}
It's a pity this method is not compilable, because of some restrictions that I can't say I really understand.
public static Builder<K, V, I extends Map<K, V>> I builder(I map) { return new Builder<K, V, I>(map); }
Or is that disappearing into the land of the horrible?
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Chris Uppal - 09 Nov 2005 13:07 GMT > I didn't like having to assign the reference to a variable. Perhaps > something like: > > Map<String, String> map = > Maps.builder(new HashMap<String, String>()) > ... I'm not clear on why you dislike the assignment ? In the version I posted (I'm assuming you've seen my other post by now) there is one variable which is assigned once, in your version there is one variable which is assigned once. Perhaps it's because you are focussing on this being a use of the Builder pattern, whereas I am only trying to create an adaptor to permit the use of the chained-send idiom (a more general notion than the Builder pattern).
For instance, in my terms, a method coded like:
void addStuffTo(List<String> list) { super.addStuffTo(list);
Stuffer.stuffing(list) .add("one") .add("two") .add("three"); }
would make perfect sense, although it is not an application of the Builder pattern (as I understand the term).
> HashMap<String, String> map = > new Builder<String, String, HashMap<String, String>>( > new HashMap<String, String>() > ) The great thing about Generics is how they make the code self-documenting...
;-)
> public static final class Builder<K, V, I extends Map<K, V>> { As a purely technical point, the fact that this is Builder pattern forces you to add the I extends Map<K, V> parameter in order to retain the concrete type of the thing under construction. In my version, since it is only an adaptor, there is no need for the third parameter. Although I /could/ add a get() method, the return type could be no more specific than Map<K, V>, rather than (say) HashMap<K, V>, since the adaptor has no reason to care about the concrete type of the object it wraps.
> It's a pity this method is not compilable, because of some restrictions > that I can't say I really understand. [quoted text clipped - 4 lines] > > Or is that disappearing into the land of the horrible? It certainly makes my eyes water a bit ;-)
I don't understand why the compiler won't accept the I parameter either -- but then I have pretty much given up on trying to see the logic in what the compiler allows and what it doesn't. I have fallen back on Voodoo programming, and just try stuff until something works :-(
BTW, returning to the previous point: Since my version doesn't carry the more complicated information about the concrete type of the target, my equivalent of that method is simpler and seems acceptable to the compiler.
-- chris
Thomas Hawtin - 09 Nov 2005 14:03 GMT >>I didn't like having to assign the reference to a variable. Perhaps >>something like: [quoted text clipped - 6 lines] > assuming you've seen my other post by now) there is one variable which is > assigned once, in your version there is one variable which is assigned once. I don't like having to mention the variable more than once. I'd also like to be able to write it as a return statement and skip the variable altogether.
> Perhaps it's because you are focussing on this being a use of the Builder > pattern, whereas I am only trying to create an adaptor to permit the use of the > chained-send idiom (a more general notion than the Builder pattern). I had actually switched to technically being an adaptor, but with the intent of a builder.
>> HashMap<String, String> map = >> new Builder<String, String, HashMap<String, String>>( >> new HashMap<String, String>() >> ) > > The great thing about Generics is how they make the code self-documenting... If it's worth documenting intent once, it's worth documenting the intent four times. Or something.
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Chris Uppal - 09 Nov 2005 13:56 GMT > It's a pity this method is not compilable, because of some restrictions > that I can't say I really understand. > > public static Builder<K, V, I extends Map<K, V>> I builder(I map) { > return new Builder<K, V, I>(map); > } Voodoo....
======= public static <K, V, I extends Map<K, V>> Builder<K, V, I> builder(I map) { return new Builder<K, V, I>(map); } =======
-- chris
Thomas G. Marshall - 09 Nov 2005 23:03 GMT Chris Uppal coughed up:
...[rip]...
> Voodoo.... > > ======= > public static <K, V, I extends Map<K, V>> > Builder<K, V, I> > builder(I map) {author has near stroke trying to read this.}
...[rip]...
 Signature Unix users who vehemently argue that the "ln" command has its arguments reversed do not understand much about the design of the utilities. "ln arg1 arg2" sets the arguments in the same order as "mv arg1 arg2". Existing file argument to non-existing argument. And in fact, mv itself is implemented as a link followed by an unlink.
Chris Uppal - 10 Nov 2005 14:06 GMT > > public static <K, V, I extends Map<K, V>> > > Builder<K, V, I> > > builder(I map) > > {author has near stroke trying to read this.} Especially ironic given the subject of this thread...
-- chris
Thomas Hawtin - 10 Nov 2005 07:33 GMT >>It's a pity this method is not compilable, because of some restrictions >>that I can't say I really understand. [quoted text clipped - 13 lines] > } > ======= I got confused by the really helpful error message. I confused it with the error you get if you use super in that situation. Looking at Chapter 18: TypeArguments can use super & &. TypeParamters cannot, but can contain TypeArguments.
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Chris Uppal - 09 Nov 2005 10:33 GMT [me:]
> > public HashSet > > makeHashSet(String... args) [quoted text clipped - 3 lines] > > Is that an abuse? It seems so to me, although I'm having difficulty articulating exactly what I find wrong about it.
The nearest I can get to it is to say that the technique /looks/ transparent but is not. I don't like such constructions at the best of times (I've griped often enough about the rate at which such "junk" is being added to the Java language); and when it comes down to [ab]using a language feature intended for one purpose in order to achieve a minor reduction of typing in an unrelated context, then I think it's going a bit too far.
Perhaps an illustration. I can easily imagine a relative beginner avoiding:
Set s = new HashSet(16); s.add("one"); s.add("two"); ... s.add("sixteen");
in favour of:
Set s = makeHashSet( "one", "two", ... "sixteen");
because the latter is "more efficient". I'm not really bothered about the actual efficiency one way or the other, but I am bothered by the fact that the latter form looks as if it's simpler than the former, when it is actually more complicated.
It's not a big deal, even in my book, and there are certainly far worse abuses possible by any standards (keeping 1e6 floats in an ArrayList for example...). In a way it's even quite a good example of how the varargs stuff works, since it focuses attention more on the implementation hackery than on the varadic nature of the method. But I don't really like it.
-- chris
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|