Search code examples
javastringlistloopsjava-stream

Handle a list of String


I have a list of String, I need to find all duplicates, also remove all children if the parents are in the list. My string can have a max 4 levels: Level0: "Root", or leave empty Level1: "Sweden", "America", etc... Level2: "Sweden.Stockholm", "America.Chicago", etc... Level3: "Sweden.Stockholm.Solna", "America.Chicago.Cicero", etc...

So if I have a list ["Sweden", "Sweden", "Sweden.Stockholm.Solna", "America.Chicago", "America.Chicago", "America.Chicago.Cicero"] then only ["Sweden", "America.Chicago"] should be returned.

How to do this with Java, preferably java 8 stream API?

The following 2 methods might be used to check if a String is a parent or child of another String:

private boolean isChildOf(String parentPath, String path) {
   return path.startsWith(parentPath.isBlank() ? parentPath : parentPath + ".") && !path.equals(parentPath);
}
private boolean isParentOf(String childPath, String path) {
   return childPath.startsWith(path + ".") && !path.equals(childPath);
}

Solution

  • Here is one way using sets. This will work with any depth of the hierarchy.

    • first add the list to a set. This removes duplicates as they aren't needed.
    • then iterate over a copy of that set and remove each element
      • if the current element is not equal to the element under test
      • and the current element starts with the element under test.
    List<String> hierarchy = List.of(
           "Sweden.Stockholm.Solna", "America.Chicago", "America.Chicago",
           "America.Chicago.Cicero", "Sweden.Stockholm.Solna","Sweden", "Sweden");
    
    Set<String> set = nodes.stream()
            .collect(Collectors.toCollection(HashSet::new));
    
    for (String str : new HashSet<>(set)) {
        set.removeIf(v -> !v.equals(str) && v.startsWith(str+"."));
    }
    
    set.forEach(System.out::println);
    

    prints

    Sweden
    America.Chicago