简体   繁体   中英

Convert nested for loop logic to for each and java stream

The code below will skip the string at index i=0,j=0 and if it occurs again anywhere. Also it will add an additional header if finaldata list is empty or whenever the finaldata string becomes of size 1000. I wish to write the same code using for each loop and java stream syntax. Can somebody help me out?

List<List<String>> completedata=new ArrayList<>(); // Suppose it contains many lists which have around 5000 strings in total
List<String> finaldata=new ArrayList<>();
String header="Heading";
String temp=null;
for(int i=0;i<completedata.size();i++) {
    for (int j = 0; j < completedata.get(i).size(); j++) {
                if ((i == 0 || j == 0) || completedata.get(i).get(j).equals(temp)) {
                    temp = completedata.get(i).get(j);
                    continue;
                }
                if (finaldata.size() == 0 || (finaldata.size() % 1000 == 0)) {
                    finaldata.add(header);
                }
                finaldata.add(completedata.get(i).get(j));
        }
}

The solution to this task comes from the definition.

  • If list of lists should be converted to plain List , Stream::flatMap is used
  • If it is needed to skip list elements at indexes 0, then Stream::skip(1) should be used.
  • If no duplicate elements are needed, then Stream::distinct should be applied.
  • If some values need to be added to the resulting list, Collectors.collectingAndThen may be used along with the IntStream.range to calculate the indexes where "Heading" needs to be inserted.

To sum it up, an example implementation can look like:

public static final List<String> formatData(List<List<String>> data, String header, int afterN) {
    return data.stream().skip(1) // skip i == 0
               .flatMap(lst -> lst.stream().skip(1)) // skip j == 0, make flat list
               .distinct() // remove duplicates
               .collect(Collectors.collectingAndThen(
                       Collectors.toList(),
                       lst -> IntStream.range(0, lst.size()).boxed()
                               .flatMap(i -> i % afterN == 0
                                       ? Stream.of(header, lst.get(i))
                                       : Stream.of(lst.get(i))
                               )
                               .collect(Collectors.toList())
               ));
}

Test

List<List<String>> data = Arrays.asList(
        Arrays.asList("Skipped line"),
        Arrays.asList("Skipped column 1", "column1", "column2", "column3"),
        Arrays.asList("Skipped column 2", "value 2.1", "value 2.2", "value 2.3"),
        Arrays.asList("Skipped column 3", "value 3.1", "value 3.2", "value 3.3"),
        Arrays.asList("Skipped column 4", "value 4.1", "value 4.2", "value 4.3"),
        Arrays.asList("Skipped column 5", "value 5.1", "value 5.2", "value 5.3", "value 5.3"),
        Arrays.asList("Skipped column 6", "6.1", "6.2", "6.3", "value 5.1", "value 4.2"),
        Arrays.asList("Skipped column 7", "7.1", "7.2", "7.3", "7.1", "7.3"),
        Arrays.asList("Skipped column 8", "8.1", "8.2", "8.3", "8.4", "8.4", "8.5")
);

// use \n to improve output, insert header after each 3 elements
List<String> finalData = formatData(data, "\nHeader", 3); 

System.out.println(finalData);

Output (without duplicate elements)

[
Header, column1, column2, column3, 
Header, value 2.1, value 2.2, value 2.3, 
Header, value 3.1, value 3.2, value 3.3, 
Header, value 4.1, value 4.2, value 4.3, 
Header, value 5.1, value 5.2, value 5.3, 
Header, 6.1, 6.2, 6.3, 
Header, 7.1, 7.2, 7.3, 
Header, 8.1, 8.2, 8.3, 
Header, 8.4, 8.5]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM