I have an class A
with multiple List
members.
class A { List<X> xList; List<Y> yList; List<Z> zList; // getters and setters } class X { String desc; String xtype; // getters and setters } class Y { String name; String ytype; //getters and setters } class Z { String description; String ztype; // getters and setters }
And a class B
with just 2 attributes:
class B { String name; String type; }
I need to iterate through the various lists in class A
and create class B
object and add to a list like this:
public void convertList(A a) { List<B> b = new ArrayList<>(); if (!a.getXList().isEmpty()) { for (final X x : a.getXList()) { b.add(new B(x.getDesc(), x.getXType())); } } if (!a.getYList().isEmpty()) { for (final Y y : a.getYList()) { b.add(new B(y.getName(), y.getYType())); } } if (!a.getZList().isEmpty()) { for (final Z z : a.getZList()) { b.add(new B(z.getDescription(), z.getZType())); } } }
As the if and for loops are repeated here.
How can I achieve this using Java streams?
Note: There is no relation between the classes X
, Y
and Z
and there is no common interface.
concat() in Java. Stream. concat() method creates a concatenated stream in which the elements are all the elements of the first stream followed by all the elements of the second stream. The resulting stream is ordered if both of the input streams are ordered, and parallel if either of the input streams is parallel.
The standard solution is to use the Stream. flatMap() method to flatten a List of Lists. The flatMap() method applies the specified mapping function to each element of the stream and flattens it.
Stream class has toArray() method to convert Stream to Array, but there is no similar method to convert Stream to List or Set. Java has a design philosophy of providing conversion methods between new and old API classes e.g. when they introduced Path class in JDK 7, which is similar to java.
Since your X
, Y
and Z
types don't have a common super-type, you have to convert them into some common type, such as Map.Entry<String,String>
.
You can create a Stream
of all pairs of names and types, and then map it to instances of B
:
List<B> b = Stream.of( a.getXList().stream().map(x -> new SimpleEntry<>(x.getDesc(),x.getXType())), a.getYList().stream().map(y -> new SimpleEntry<>(y.getName(),y.getYType())), a.getZList().stream().map(z -> new SimpleEntry<>(z.getDescription(),z.getZType()))) .flatMap(Function.identity()) .map(e -> new B(e.getKey(), e.getValue())) .collect(Collectors.toList());
Or directly generate B
instances:
List<B> b = Stream.of( a.getXList().stream().map(x -> new B(x.getDesc(),x.getXType())), a.getYList().stream().map(y -> new B(y.getName(),y.getYType())), a.getZList().stream().map(z -> new B(z.getDescription(),z.getZType()))) .flatMap(Function.identity()) .collect(Collectors.toList());
You can use Stream.concat()
like following
public List<B> convertList (A a) { return Stream.concat(Stream.concat(a.getXList().stream().map(x -> new B(x.getDesc(), x.getXType())) , a.getYList().stream().map(y -> new B(y.getName(), y.getYType()))) , a.getZList().stream().map(z -> new B(z.getDescription(), z.getZType()))).collect(Collectors.toList()); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With