简体   繁体   English

排序哈希图Java键的有效方法

[英]Efficient way to sort keys of hashmap Java

Given a hashMap and return the keys of hashmap in sorted order in arraylist This is the function API: 给定一个hashMap并在arraylist中按排序顺序返回hashmap的键,这是函数API:

ArrayList<String> foo(HashMap<String,String> hashMap)
{
}

Now, there are two ways to solve problem: 现在,有两种方法可以解决问题:

  1. Take all keys in arraylist and then sort it 取得arraylist中的所有键,然后对其进行排序
  2. Store the keys of map in treeset and then store in arraylist and return. 将map键存储在树集中,然后存储在arraylist中并返回。

Former approach will not uses additional space complexity as i am not using treeset. 前一种方法不会使用额外的空间复杂度,因为我没有使用树集。 The keys are alphanumeric. 键是字母数字。 Which one will have less time complexity. 哪一个时间复杂度更低。 Any other way you would recommend? 您会建议其他方式吗?

To a certain degree that depends on what you intend to do with the "sorted" thingy afterwards. 在某种程度上取决于您打算对事后进行“分类”处理。

But in your case, you are saying: in the end, you want a sorted list; 但是,对于您而言,您是在说:最后,您需要一个排序列表; thus: directly create that a list, sort and return it! 因此:直接创建该列表,进行排序并返回!

Even when both approaches have the same complexity (O(n*log(n)) - keep in mind that sorting that list can be probably faster (because it just has to move elements in an array, instead of having to create lots of tree nodes). 即使两种方法都具有相同的复杂度(O(n * log(n))-请记住,对列表进行排序可能会更快(因为它只需要移动数组中的元素,而不必创建大量树节点)。

In other words: creating that TreeList to then turn it into an ArrayList means for sure a lot of copying will go on. 换句话说:创建该TreeList然后将其转换为ArrayList意味着可以确保进行大量复制。 Simply avoid that! 只需避免这种情况!

The answer is going to depend on the domain of the keys. 答案将取决于密钥的域。 There are some situations in which storing the keys in a sorted order (ie in a tree) is very efficient. 在某些情况下,按排序顺序(即,在树中)存储密钥非常有效。 However I would suggest in most cases it will be more efficient to sort once, on retrieval. 但是,我建议在大多数情况下,对检索进行一次排序将更为有效。

I tried the following code: 我尝试了以下代码:

    Map<Integer, Integer> map = new HashMap<>();
    Random random = new Random();
    random.ints(1000000).forEach(n -> map.put(n, n));
    long time1 = System.currentTimeMillis();
    Set<Integer> set = new TreeSet<>(map.keySet());
    List<Integer> list1 = new ArrayList<>(set);
    long time2 = System.currentTimeMillis();
    List<Integer> list2 = new ArrayList<>(map.keySet());
    Collections.sort(list2);
    long time3 = System.currentTimeMillis();
    System.out.println("Set approach " + (time2 - time1));
    System.out.println("Sort approach " + (time3 - time2));

The result was 3768 and 1824 which I suspect would be fairly typical of the two approaches. 结果是3768和1824,我怀疑这在这两种方法中是相当典型的。

As a matter of interest I also tried: 出于兴趣,我还尝试了:

   List<Integer> list3 = map.keySet().stream().sorted().collect(Collectors.toList());

The result was 537 milliseconds: more than 3 times faster than the Collections.sort approach. 结果为537毫秒:比Collections.sort方法快3倍以上。

However when I retried with 10 million entries, the three approaches took 但是,当我重试一千万个条目时,采用了三种方法

  • 26,916 for TreeSet TreeSet为26,916
  • 2,845 for Collection.sort 2,845 for Collection.sort
  • 13,580 for Stream.sorted 13,580 for Stream.sorted

The conclusion is that sorting the array once is much more efficient for largish maps. 结论是,对大型地图,对数组进行一次排序效率更高。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM