Easy way to create a list of strings?

  • Thread starter brightoceanlight
  • Start date
B

brightoceanlight

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");


?
 
C

chris_k

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
 
Z

zero

(e-mail address removed) wrote in @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
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");


?

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));
 
R

Roedy Green

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 );
 
C

Chris Uppal

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
 
M

Mike Schilling

Chris Uppal said:
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");

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?
 
T

Thomas Hawtin

Mike said:
Is that an abuse? If, so I suppose the "right" way to do this is

HashSet makeHashSet(String... args)
^ said:
{
HashSet hs = new HashSet<String>;
^ said:
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
 
C

Chris Uppal

Mike Schilling wrote:

[me:]
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
 
C

Chris Uppal

Thomas said:
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
 
C

Chris Uppal

I said:
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...


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);
}
}
==================
 
T

Thomas Hawtin

Chris said:
Thomas Hawtin wrote:




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)

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
 
C

Chris Uppal

Thomas said:
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.

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?

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
 
C

Chris Uppal

Thomas said:
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
 
T

Thomas Hawtin

Chris said:
Thomas Hawtin wrote:




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.

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.
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
 
T

Thomas G. Marshall

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.


--
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.
 
T

Thomas G. Marshall

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]...

--
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.
 
R

Roedy Green

// 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.

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.
 
T

Thomas G. Marshall

Roedy Green coughed up:
On Wed, 09 Nov 2005 18:01:38 GMT, "Thomas G. Marshall"
<[email protected]> coughed this
wad of congealed sputum up from his tubercular lungs:
LOL

// 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.

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.


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.
 
T

Thomas Hawtin

Chris said:
Thomas Hawtin wrote:




Voodoo....

=======
public static <K, V, I extends Map<K, V>>
Builder<K, V, I>
builder(I map)
{
return new Builder<K, V, I>(map);
}
=======

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top