简体   繁体   中英

Equivalent to Arrays.asList() but for arrays?

I'd like a convenience method to take a set of parameters and return an array, much like Arrays.asList(T... items) will take a set of parameters and return a List<T> of those items.

It's easy enough to write one, but does one already exist in java?

UPDATE My bad! I didn't realize the question was so unclear. Your questions have forced me to realize that the question isn't quite the question I thought it was.

I have several calls like the following that place various key/values into a Map:

        put( Key.get(A.class), new Key[] { Key.get(X.class), Key.get(Y.class), Key.get(Z.class)});

... where the map is of type Map<Key<? extends Foo>,Key<? extends Foo>[]> Map<Key<? extends Foo>,Key<? extends Foo>[]>

I was looking for a typesafe and succinct way to execute the above statement, and I thought that something like the following would work:

        put( Key.get(A.class), toArray( Key.get(X.class), Key.get(Y.class), Key.get(Z.class)));

... where toArray() is defined as something like

private static <T> T[] toArray( T... t ) {
    return t;
}

However, it turns out that this solution is not typesafe itself, and thus it's really not much more succinct than just creating a new array manually using new . This was the first cause of my misunderstanding.

I thought that I could get typesafety by using a List instead of an array and then using Arrays.asList() to populate the values of the list, but it turns out that that's not typesafe either. This was the second cause of my misunderstanding. I thought that Arrays.asList() would make this statement more succinct than it actually does, and thus I was looking for something that would do the same for me for arrays.

So I suppose the question is really - Is there a succinct way to get typesafety in the above situation?

Arrays already have such a shortcut syntax:

String[] strArray = {"one", "two", "three"};

In response to your update:

As it seems like you discovered, arrays of parameterized types can never be type-safe. This is one of several limitations due to the fact that arrays and generics are like oil and water .

A varargs method such as Arrays.asList isn't spared from this limitation since varargs works by implicitly creating an array of the comma delimited arguments. In order to have type-safety, you'll need to avoid any solution involving arrays, including varargs.

First, I recommend you change your map's type to hold List s instead of arrays:

Map<Key<? extends Foo>, List<Key<? extends Foo>>> map = new HashMap<>();

And then build a List before putting it in the Map :

List<Key<? extends Foo>> lst = new ArrayList<>();
lst.add(Key.get(X.class));
lst.add(Key.get(Y.class));
lst.add(Key.get(Z.class));
map.put(Key.get(A.class), lst);

If you want it all in one statement, it's going to be trickier without varargs. Guava's ImmutableList exposes the of factory methods taking up to 12 elements before falling back to varargs. If the List s in the map aren't going to be modified later, you could store ImmutableList<Key<? extends Foo>> ImmutableList<Key<? extends Foo>> and use:

map.put(
    Key.get(A.class),
    ImmutableList.of(Key.get(X.class), Key.get(Y.class), Key.get(Z.class))
);

In fact you could still take advantage of those factory methods even if the List needs to be modifiable by copying the returned ImmutableList :

map.put(
    Key.get(A.class),
    Lists.newArrayList(ImmutableList.of(
        Key.get(X.class),
        Key.get(Y.class),
        Key.get(Z.class)
    ))
);

But then you're introducing overhead just for the sake of style.


Side note: if you do happen to be using Guava, you might look at using a Multimap instead of a Map of List s.

What would such a method do that the constructor for the array doesn't already?

String foo = "FOO";
String bar = "BAR";
String[] strings = new String[]{foo, bar};

How about

public static class ToArray {
    public static <T> T[] toArray(T... items) {
        return items;
    }                
}

public void example() {
    String[] strings = ToArray.toArray("fred", "bob");
}

?

In order to get a Set and return a List you could use an ArrayList :

Set<String> set = new HashSet<String>();
set.add("str1");
set.add("str2");
set.add("str3");

List<String> list = new ArrayList<String>(set);

If you want an array from a list you could do something like:

myList.toArray();
// or even
String[] myStringArray = myList.toArray(new String[]);

Is this what you want? This will return an array because Java treats the varargs construct as an array . I don't know how to genericize it though.

public Object argsToArray(Object... args) {
return args;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM