Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

casting & generics to enable list concatenation in Java 8

Apologies that is probably the worst Title I've used but I can't quite think how to word it.

I'm calling a method table.getColData(COL_1) which returns a generic

public <T extends Object> List<T> getColData(final String col)

I am calling it twice and getting two lists of strings. I want to concatenate these and have ended up with this -

List<String> a = table.getColData(col1);
List<String> b = table.getColData(col2);

List <String> c = Stream.concat(a.stream(), b.stream()).collect(Collectors.toList());

which works nicely I think. I can't find a way to avoid the 2 declarations though without getting an error as the concat thinks it has a list of objects that are not Strings (prompt: change type of c to List<Object>) ?

Is there an easy way to do this to make it look a little more polished?!

like image 262
gringogordo Avatar asked Aug 21 '18 13:08

gringogordo


1 Answers

You are limited by the inference of the compiler.

List <String> c = Stream.concat(getColDataStream(col1).stream(), getColDataStream(col2).stream()).collect(Collectors.toList());

cannot compile because getColDataStream() return is inferred as List<Object> as you don't specify a target type from the invocation side.
You can concatenate two streams of List<Object> but it not will produce Stream<String> but Stream<Object>.
Introducing two intermediary variables is not necessary the best way.

1) As alternative as suggested by Holger you could specify the T type from the target side :

 Stream.concat(table.<String>getColData(col1).stream(), table.<String>getColData(col2).stream()) 
       .collect(Collectors.toList());

2) You could also transform Stream<Object> to Stream<String>in a map() operation :

List<String> c = Stream.concat(table.getColData(col1).stream(), table.getColData(col2).stream())
                           .map(s -> (String) s)
                           .collect(Collectors.toList());

3) or introducing an additional method that prevents any explicit cast by concatenating streams of the lists, and collecting it in a List that it returns :

public <T> List<T> concatAndCollectToList(final List<T> a, List<T> b) {
    return Stream.concat(a.stream(), b.stream())
                 .collect(Collectors.toList());
}

You can now do just :

List<String> c = concatAndCollectToList(table.getColData(col1), table.getColData(col2));
like image 97
davidxxx Avatar answered Sep 24 '22 17:09

davidxxx