How to convert multiple list into single list using Java streams?

Dar*_*row 23 java java-stream

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    
}
Run Code Online (Sandbox Code Playgroud)

And a class B with just 2 attributes:

class B {
    String name;
    String type;     
}
Run Code Online (Sandbox Code Playgroud)

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()));
      }
    }    
}
Run Code Online (Sandbox Code Playgroud)

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.

Era*_*ran 18

由于您的X,YZ类型没有通用的超类型,因此您必须将它们转换为某种通用类型,例如Map.Entry<String,String>.

您可以创建Stream所有名称和类型对,然后将其映射到以下实例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());
Run Code Online (Sandbox Code Playgroud)

或者直接生成B实例:

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());
Run Code Online (Sandbox Code Playgroud)


jan*_*024 13

您可以使用Stream.concat()如下

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());
}
Run Code Online (Sandbox Code Playgroud)

  • @Hadi J 我在 lambda 表达式中遇到错误的返回类型。B 无法转换为 R (3认同)
  • 我的错是我在错误的地方戴了紧牙套。这看起来不错。谢谢! (2认同)

Nik*_*hil 7

由于您没有通用接口,因此您必须使用一种forEach方法来遍历每个列表。

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())));
Run Code Online (Sandbox Code Playgroud)


Ekl*_*vya 5

您对X、Y、Z类使用不同的属性,并且没有通用接口,您可以在列表中一一添加。

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()));
Run Code Online (Sandbox Code Playgroud)