【问题标题】:Sort Map<String, Integer> Largest First Into List<String> Efficiently?将 Map<String, Integer> 最大的优先排序到 List<String> 有效?
【发布时间】:2015-07-02 20:33:28
【问题描述】:

我有一个ConcurrentMap&lt;String, Integer&gt;,我想从它那里得到一个List&lt;String&gt;,它的字符串映射到第一大整数,第二大整数,等等。

现在我有一些类似的东西:
循环遍历地图的keySet
在该循环中,循环通过“排序”List&lt;String&gt;
继续循环,直到键字符串的相应值小于“已排序”List 的元素i,然后将其插入。

现在这将起作用,但我怀疑它是否非常有效。 Java 8 是否有任何内置的排序算法可以帮助我?

【问题讨论】:

  • 如果你展示你的代码而不是描述它,你会更容易理解你在做什么。
  • 抱歉,我没有测试我的代码,也不想用可能不正确的代码混淆人们
  • 这也是数据结构中的一个问题。我会创建一个逆映射 - 即从 Integer 到 List 的映射。我将使用TreeMap,而不是使用HashMap,其中键顺序基于散列函数,因此键在插入地图时实际上是排序的。然后,我可以遍历已经按其值排序的键,我可以获得与该整数键匹配的字符串列表,我可以将它连接到一个主字符串列表,这是您需要的最终列表
  • 尽管您可能最好使用内置的方式来做到这一点,就像他们在答案中描述的那样。我的算法正在重新发明轮子

标签: java sorting java-8


【解决方案1】:

使用流,你可以这样写:

List<String> sorted = map.entrySet().stream()
                         .sorted(reverseOrder(comparing(Entry::getValue)))
                         .map(Entry::getKey)
                         .collect(toList());

或者如 Holger 所说:

List<String> sorted = map.entrySet().stream()
                         .sorted(comparingByValue(reverseOrder()))
                         .map(Entry::getKey)
                         .collect(toList());

注意静态导入:

import static java.util.Collections.reverseOrder;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;

我不知道这是否比您的方法更有效,但您可以对两者进行分析并根据实际测量结果做出决定。

【讨论】:

  • 简短且使用 Java 8,完美!谢谢!
  • 很抱歉打扰您。我想知道为什么.sorted(Comparator.comparing(Map.Entry::getValue)) 编译/工作正常,但.sorted(Comparator.comparing(Map.Entry::getValue).reversed()) 不想编译声称getValue 不需要参数,但它找到Object。如果我将泛型类型显式添加到Map.Entry&lt;String,Integer&gt;,它也会编译。您认为我应该针对这种类型推断问题创建单独的问题,还是我错过了一些已经在 SO question 上已经提出的明显事实?
  • @Pshemo 是的,这很烦人 - 我认为这是由于类型推断在方法链接方面效率不高......另请参阅:stackoverflow.com/questions/25172595/…
  • 谢谢。这个问题与我的问题非常接近。所以现在我可能会使用你的方式或comparing(extractor, comparator).sorted(Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder())) 这样也可以正常工作,无需显式添加泛型类型。
  • @Pshemo: It’s even easier: .sorted(comparingByValue(reverseOrder()))
【解决方案2】:

是的,确实如此。你可以这样做:

ConcurrentMap<String, Integer> map = /* something */;

// entrySet just returns a view of the entries, so copy it into a new List
List<Map.Entry<String, Integer>> entries = new ArrayList<>(yourMap.entrySet());

// sort entries by their int values
Collections.sort(entries, (entry1, entry2) -> Integer.compare(entry1.getValue(), entry2.getValue()));

// copy just the keys into a new List
List<String> result = new LinkedList<>();
for (Map.Entry<String, Integer> entry : entries) {
  result.add(entry.getKey());
}

【讨论】:

    【解决方案3】:
    import java.util. TreeSet;
    

    导入 java.util.Set; 导入 java.util.concurrent.ConcurrentHashMap;

    公共类测试{

    public static void main(String[] args){
        ConcurrentHashMap< String, Integer> map = new ConcurrentHashMap<String , Integer>();
        map.put("Fish", 1);
        map.put("Bird", 100);
        map.put("Reptile", 2);
        map.put("Mammal", 10);
        TreeSet <Integer> sortedList = new TreeSet <Integer>(map.values());
        for(Integer i :sortedList){
            System.out.println(i);
        }
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-25
      • 2017-07-18
      • 2022-09-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多