【问题标题】:Group JAVA Map keys based on tokens in string key根据字符串键中的标记对 JAVA Map 键进行分组
【发布时间】:2019-02-08 04:25:44
【问题描述】:

我有这个要求,我需要解析一个文本文件并从中提取 n-gram 并将 n-gram 映射及其计数存储在映射中。现在,Map 键是可以包含 1,2,3 个单词的字符串。

例如("mango", 10), ("facbook朋友", 6), ("有钱人", 3) 1

示例映射:

("芒果", 2)

("苹果", 1)

("芒果树", 5)

("脸书好友", 3)

(“脸书人”, 8)

("买新表", 2)

现在,我想根据地图键中的关键字标记长度对地图进行排序。就像所有 1 个单词的键映射应该首先在映射中,然后是 2 个单词,然后是 3 个单词映射。

我尝试使用 TreeMap,但主要挑战是为排序顺序定义 compareTo 函数。有任何想法吗?像下面的方法不起作用。

    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);

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

【问题讨论】:

  • 定义自己的 compareTo 有什么问题,您必须比较字符串中空格的基数或数量,而不是长度。
  • @viveksinghggits 如果我只根据空格数定义 compareTo,那么地图将只有 3 个映射。
  • @Santosh 我需要根据键中的单词进行排序,而不是字符串值。
  • 如何拥有两个具有相同键的映射条目? IE。 ("facebook 朋友", 3) 和 ("facebook 朋友", 8) 是不可能的,对吧?

标签: java collections hashmap treemap


【解决方案1】:

以下代码按顺序插入记录。

    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);

【讨论】:

  • 尝试添加更多值。这只会存储 3 个映射。
  • 是的。我错过了一个条件。请检查更新后的代码。
  • 是的,这似乎是准确的。
【解决方案2】:

您可以使用Collectors.toMap 和订购的地图供应商来做到这一点,如下所示:

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);

输出

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

您也可以使用以下.sorted(... 行:

.sorted(Map.Entry.comparingByKey(Comparator.comparingInt(k -> k.split(" ").length)))

【讨论】:

  • 我在想一些创造性的方法来使用 compareTo 以便我们在插入时有一个排序的地图,但这解决了问题。
  • @quintin 啊,现在我明白你的意思了。请参阅上面的更新。
  • 我不认为 new TreeMap(Comparator.comparingInt(k -> k.split(" ").length));会工作
  • 尝试添加 3 个以上的映射。这就是 copmareTo 的行为。
  • 好的,我加了 4,它仍然有效.. 你一定是犯了一些错误
猜你喜欢
  • 2018-10-26
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 1970-01-01
  • 2012-12-16
  • 2019-03-23
相关资源
最近更新 更多