Search code examples
javasortingarraylistlinkedhashmap

Sorting LinkedHashMap<String, ArrayList<String>> by counting the occurrences in ArrayList<String> problem


I have:

ArrayList<String> miss;
LinkedHashMap<String, ArrayList<String>> map;

How can i sort "maps" by counting the occurrences in "miss"? For example:

  1. miss => [3, 7]
  2. maps => {1=[0, 3, 6], 4=[2, 3, 4], 6=[0, 3, 7], 11=[1, 3, 6], 17=[2, 6, 11]}

And i want to get:

maps => {6=[0, 3, 7], 1=[0, 3, 6], 4=[2, 3, 4], 11=[1, 3, 6], 17=[2, 6, 11]}


Solution

  • The following solution is based on using Stream API

    1. Count the frequencies of elements from miss in each list value of maps and collect the frequency into some object (e.g. a list)
    2. Sort the new object by the frequency in the reverse order and then by the key of initial map (note: the key may need to be converted into int to provide the expected output: 1, 4, 11; comparing the keys as String returns the order 1, 11, 4)
    3. Build the resulting map using Collectors.toMap with LinkedHashMap::new supplier
    List<String> miss = List.of("3", "7");
    Map<String, List<String>> maps = Map.of(
         "1", List.of("0", "3", "6"),
         "4", List.of("2", "3", "4"),
         "6", List.of("0", "3", "7"),
        "11", List.of("1", "3", "6"),
        "17", List.of("2", "6", "11")
    );
    
    Map<String, List<String>> sorted = maps.entrySet()
        .stream()
        .map(e -> Arrays.asList(e, 
            e.getValue().stream()
                .mapToInt(i -> (int) miss.stream().filter(i::equals).count())
                .sum()
        ))
        .sorted(Comparator
            .<List>comparingInt(ee -> (int) ee.get(1)).reversed()
            .thenComparingInt(ee -> Integer.parseInt(((Map.Entry<String, List<String>>) ee.get(0)).getKey()))
        )
        .map(ee -> (Map.Entry<String, List<String>>) ee.get(0))
        .collect(Collectors.toMap(
            Map.Entry::getKey,
            Map.Entry::getValue,
            (v1, v2) -> v1,
            LinkedHashMap::new
        ));
    
    System.out.println(sorted);
    

    Output:

    {6=[0, 3, 7], 1=[0, 3, 6], 4=[2, 3, 4], 11=[1, 3, 6], 17=[2, 6, 11]}