0

I have this requirement where I need to parse a text file and extract n-grams from it and store the n-gram mapping with their count in a map. Now, the Map key is string which can have 1,2,3 words in it.

e.g. ("mango", 10), ("facbook friend", 6), ("the rich guy", 3) 1<=n<=3

Example mapping:

("mango", 2)

("apple", 1)

("mango tree", 5)

("facebook friend", 3)

("facebook people", 8)

("Bougth new watch", 2)

Now, I want to sort the map based on keyword tokens length in map key. like all 1 word key mapping should be first in map then 2 words then 3 words mapping.

I tried using TreeMap but the main challenge was to define compareTo function for the sorting order. Any ideas? Like below method do not work.

    Map<String, Integer> m = new TreeMap<>(Comparator.comparingInt(k -> k.split(" ").length));

    m.put("mango tree", 5);
    m.put("Bought new watch", 2);
    m.put("apple", 1);
    m.put("mango tree", 5);
    m.put("Bought new watch", 2);
    m.put("appl1", 1);
    m.put("mango 1", 5);
    m.put("Bought 1 watch", 2);
    m.put("appl2", 1);
    m.put("mango 2", 5);
    m.put("Bought 2 watch", 2);
    m.put("appl3", 1);
    System.out.println(m);

Output: {apple=1, mango tree=5, Bought new watch=2}

quintin
  • 812
  • 1
  • 10
  • 35

2 Answers2

1

The following code inserts the records in order.

    SortedMap<String, Integer> m = new TreeMap<>(new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            int s2length = s2.split(" ").length;
            int s1length = s1.split(" ").length;
            return s2length>s1length?-1:s2length==s1length && s2.equals(s1)?0:1;
        }
    });

    m.put("mango tree", 5);
    m.put("you have to check this out too", 1);
    m.put("apple", 1);
    m.put("apple", 5);
    m.put("you have to check this out", 1);
    m.put("check this out", 1);
    m.put("Bought new watch", 2);
    m.put("check this out too", 1);

    System.out.println(m);
Innovationchef
  • 338
  • 2
  • 10
0

You can do it using Collectors.toMap with an ordered map supplier like so:

Map<String, Integer> m = new HashMap<>();
m.put("mango tree", 5);
m.put("Bought new watch", 2);
m.put("apple", 1);

LinkedHashMap<String, Integer> sortedMap = m.entrySet().stream()
        .sorted(Comparator.comparingInt(e -> e.getKey().split(" ").length))
        .collect(Collectors.toMap(Map.Entry::getKey,
                Map.Entry::getValue,
                (o1, o2) -> o1,
                LinkedHashMap::new));

System.out.println(sortedMap);

Output

{apple=1, mango tree=5, Bought new watch=2}

You can also use the following .sorted(... line:

.sorted(Map.Entry.comparingByKey(Comparator.comparingInt(k -> k.split(" ").length)))
Kartik
  • 7,677
  • 4
  • 28
  • 50