Converting Java List to another using java streams

213 Views Asked by At

I have a class Test

public class Test{
  String codes;
  String field 1;
  ....
  String field n;
}

I have a list of test objects

List<Test> objects, code can be one or more with a comma separated
testObj1("A", "field1".."fieldn")
testObj2("B,C", ...)
testObj3("D,E,F", ....)
testObj4("G", ...)

Trying to convert this list1 to new list2 with each code A, B, C... to its own object by retaining the remaining fields.

List<Test>
testObj1("A", ....)
testObj2("B", ....)
testObj3("C", ....)

list1.stream().collect(Collectors.toList())

I achieved this using loops (Sudo code) but looking for better logic

for(loop thru list1){
  String[] codesArr = testObj1.codes.split(",");
  for (String code : codesArr) {
    //Create new Obj 
    Test obj = new Test(code, testObj1.copyotherfields);
    //Add obj to list2
  }
}
3

There are 3 best solutions below

0
Naman On BEST ANSWER

You can use Stream.map with flatMap as :

List<Test> finalList = list1.stream()
        .flatMap(e -> Arrays.stream(e.getCodes().split(","))
                .map(c -> new Test(c, e.getField1(), e.getFieldn())))
        .collect(Collectors.toList());

This assumes that your Test class would have a constructor similar to the following implementation:

class Test {
    String codes;
    String field1;
    String fieldn;

    // would vary with the number of 'field's
    Test(String codes, String field1, String fieldn) {
        this.codes = codes;
        this.field1 = field1;
        this.fieldn = fieldn;
    }
    // getters and setters
}
0
GBlodgett On

You can simplify this to:

List<Test> copy = list.stream()
                      .map(e -> Arrays.stream(e.codes.split(""))            
                                      .map(c -> new Test(c, e.otherField))
                     .collect(Collectors.toList()))
                     .findAny().orElse(...);

Which will stream through the given list, then stream through the Array yielded from split() and map to a new Test object and collect it to a List. It retrieves it through findAny(), which returns an Optional<List<Test>>, so I would recommend using orElse to retrieve a default value.

1
Blake Ordway On

You can use a map function and then flatMap it to be like so:

List<String> testList = Arrays.asList("one,two,three,four", "five", "six", "seven", 
"eight, nine", "ten");

 List<String> reMappedList = testList.stream()
 .map(s -> {
     String[] array = s.split(",");
     return Arrays.asList(array);
 })
 .flatMap(List::stream)
 .collect(Collectors.toList());

 System.out.println(reMappedList);