How to iterate list of list on a condition and to return value in Map?

Viewed 78
public class ClassOne {
   private Long id;
   private List<ClassTwo> secondClass;
}

public class ClassTwo {
   private Long link;
   private ClassThree thirdClass;
}

public class ClassThree {
   private Long number;
}

Datas available :

List<classOne> classOneList  
List<Long> referencedNumbers

Requirements :

To iterate the classOneList and store the values in Map<Long, <ListLong>> by having id from ClassOne as 'key' and link from ClassTwo as 'values' only if referencedNumbers contains a number from ClassThree.

Note : It should be implement only using streams rather than loops and restricted to Java 8

  • Return type should be: Map<Long, List<Long>>
  • For more Clarity: Map<id, List<link>>

Please let me know for any more clarifications

1 Answers

I added extra code to classes ClassOne, ClassTwo and ClassThree in order to write a SSCCE.

The implementation of your requirement (as stated in your question) is in method main of class Main.

More explanations after the code.

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {
        ClassThree c3 = new ClassThree(3L);  // create 'ClassThree' instance
        ClassTwo c2 = new ClassTwo(5L, c3);  // create 'ClassTwo' instance
        List<ClassTwo> c2s = List.of(c2);    // create 'List<ClassTwo>'
        ClassOne c1 = new ClassOne(0L, c2s); // create 'ClassOne' object
        List<ClassOne> classOneList = List.of(c1);
        List<Long> referencedNumbers = List.of(3L);

        // Obtains map value (see below), i.e. list of links.
        Function<ClassOne, List<Long>> valMapper = cOne -> cOne.getSecondClass()
                                                               .stream() // Stream<ClassTwo>
                                                               .map(cTwo -> cTwo.getLink()) // Stream<Long>
                                                               .collect(Collectors.toList()); // List<Long>

        Map<Long, List<Long>> map = classOneList.stream()
                                                .filter(cOne -> cOne.getSecondClass().stream()
                                                                                     .filter(cTwo -> referencedNumbers.contains(cTwo.getThirdClass().getNumber()))
                                                                                     .findFirst()
                                                                                     .isPresent())
                                                .collect(Collectors.toMap(cOne -> cOne.getId(), // obtains map key.
                                                                          valMapper));
        System.out.println(map);
    }
}

class ClassOne {
    private Long id;
    private List<ClassTwo> secondClass;

    public ClassOne(Long id, List<ClassTwo> c2s) {
        this.id = id;
        secondClass = c2s;
    }

    public Long getId() {
        return id;
    }

    public List<ClassTwo> getSecondClass() {
        return secondClass;
    }
}

class ClassTwo {
    private Long link;
    private ClassThree thirdClass;

    public ClassTwo(Long ln, ClassThree c3) {
        link = ln;
        thirdClass = c3;
    }

    public Long getLink() {
        return link;
    }

    public ClassThree getThirdClass() {
        return thirdClass;
    }
}

class ClassThree {
    private Long number;

    public ClassThree(Long num) {
        number = num;
    }

    public Long getNumber() {
        return number;
    }
}

For each element in classOneList, the "filter" searches its secondClass list for a number that appears in referencedNumbers.

From the filtered list, I create the map.

When I run the above code, it outputs the following:

{0=[5]}

In other words, the id from ClassOne is 0 (zero) – which is the map key and the map value is a list containing a single element which is the value of link in ClassTwo.

Related