23

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.

4
  • have you tried using FlatMap, if not have a look here. stackoverflow.com/questions/23112874/… Commented May 25, 2020 at 10:10
  • Does X,Y and Z extend the same base class or implement the same interface containing both getName and getType? Commented May 25, 2020 at 10:11
  • Address the question properly because you are having multiple lists but passing x,z,y as a type but expecting a list of B. Commented May 25, 2020 at 10:16
  • 1
    @JoakimDanielson Updated the question. There is no base class or interface. The attributes are all different in those classes. I need to convert to Class B based on the getters of each class. Commented May 25, 2020 at 10:27

4 Answers 4

18

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());
Sign up to request clarification or add additional context in comments.

1 Comment

What would be the point of generating a SimpleEntry and then mapping it to B?
13

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());
}

3 Comments

@Hadi J I'm getting Bad return type in lambda expression. B cannot be converted to R
I have run this version in my local machine it works for me
My bad I had close braces at the wrong place. This looks good. Thanks!
6

Since you don't have a common interface, you would have to use a forEach method to iterate through each list.

a.getXList().forEach(i -> b.add(new B(i.getDesc(), i.getXType())));
a.getYList().forEach(i -> b.add(new B(i.getName(), i.getYType())));
a.getZList().forEach(i -> b.add(new B(i.getDescription(), i.getZType())));

1 Comment

OP needs java streams answer you can mention in your answer for non-stream answer.
4

You are using the different property for X, Y, Z class, and not having common interface, you can add one by one in the list.

b.addAll(a.getXList().stream().map(x ->new B(x.getDesc(), x.getXType())).collect(Collectors.toList()));
b.addAll(a.getYList().stream().map(y ->new B(y.getName(), y.getYType())).collect(Collectors.toList()));
b.addAll(a.getZList().stream().map(z ->new B(z.getDescription(), z.getZType())).collect(Collectors.toList()));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.