Java有序地图

时间:2009-03-19 18:11:02

标签: java collections

在Java中,是否存在一个像Map一样的对象来存储和访问键/值对,但是可以返回一个有序的键列表和一个有序的值列表,这样键和值列表就在同一个购买?

因此,作为代码解释,我正在寻找与我虚构的OrderedMap相似的东西:

OrderedMap<Integer, String> om = new OrderedMap<>();
om.put(0, "Zero");
om.put(7, "Seven");

String o = om.get(7); // o is "Seven"
List<Integer> keys = om.getKeys();
List<String> values = om.getValues();

for(int i = 0; i < keys.size(); i++)
{
    Integer key = keys.get(i);
    String value = values.get(i);
    Assert(om.get(key) == value);
}

10 个答案:

答案 0 :(得分:351)

SortedMap界面(实施TreeMap)应该是你的朋友。

界面包含以下方法:

  • keySet()以升序返回一组键
  • values()以相应键的升序返回所有值的集合

因此,此界面完全满足您的要求。但是,密钥必须具有有意义的顺序。否则,您可以使用LinkedHashMap,其中订单由插入订单确定。

答案 1 :(得分:191)

  

是否有一个对象用作存储和访问键/值对的Map,但是可以返回键的有序列表和有序的值列表,这样键和值列表的顺序相同? / p>

您正在寻找java.util.LinkedHashMap。您将获得Map.Entry<K,V>对的列表,它们总是以相同的顺序迭代。该顺序与您放置项目的顺序相同。或者,使用java.util.SortedMap,其中键必须具有自然顺序或由{{{ 1}}。

答案 2 :(得分:17)

LinkedHashMap维护密钥的顺序。

java.util.LinkedHashMap似乎就像普通的HashMap一样工作。

答案 3 :(得分:6)

我认为您从框架中获得的最接近的集合是SortedMap

答案 4 :(得分:4)

您可以利用可以按升序或降序键访问和遍历的NavigableMap接口。此接口是intended to supersede SortedMap接口。 Navigable地图通常根据其键的自然顺序或在地图创建时提供的比较器进行排序。

它有三个最实用的实现:TreeMapImmutableSortedMapConcurrentSkipListMap

TreeMap示例:

TreeMap<String, Integer> users = new TreeMap<String, Integer>();
users.put("Bob", 1);
users.put("Alice", 2);
users.put("John", 3);

for (String key: users.keySet()) {
  System.out.println(key + " (ID = "+ users.get(key) + ")");
}

输出:

Alice (ID = 2)
Bob (ID = 1)
John (ID = 3)

答案 5 :(得分:3)

答案 6 :(得分:3)

从Java 6开始,TreeMap也存在非阻塞线程安全替代方案。 请参阅ConcurrentSkipListMap

答案 7 :(得分:0)

我已使用简单哈希图,链接列表和集合对值进行分类。

import java.util.*;
import java.util.Map.*;
public class Solution {

    public static void main(String[] args) {
        // create a simple hash map and insert some key-value pairs into it
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("Python", 3);
        map.put("C", 0);
        map.put("JavaScript", 4);
        map.put("C++", 1);
        map.put("Golang", 5);
        map.put("Java", 2);
        // Create a linked list from the above map entries
        List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
        // sort the linked list using Collections.sort()
        Collections.sort(list, new Comparator<Entry<String, Integer>>(){
        @Override
         public int compare(Entry<String, Integer> m1, Entry<String, Integer> m2) {
        return m1.getValue().compareTo(m2.getValue());
        }
      });
      for(Entry<String, Integer> value: list) {
         System.out.println(value);
     }
   }
}

输出为:

C=0
C++=1
Java=2
Python=3
JavaScript=4
Golang=5

答案 8 :(得分:0)

tl; dr

要使Map< Integer , String >保持按键排序的顺序,请使用实现SortedMap / NavigableMap接口的两个类之一:

  • TreeMap
  • ConcurrentSkipListMap

如果要在单个线程中操作地图,请使用第一个TreeMap。如果要跨线程进行操作,请使用第二个ConcurrentSkipListMap

有关详细信息,请参见下表和以下讨论。

详细信息

这是我制作的图形表,显示了与Java 11捆绑在一起的十个Map实现的功能。

NavigableMap的界面首先应该是SortedMap。逻辑上SortedMap应该被删除,但是不能删除,因为某些第三方地图实现可能正在使用接口。

如该表所示,只有两个类实现SortedMap / NavigableMap接口:

这两种方法都按其自然顺序(使用ComparablecompareTo)接口的https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Comparable.html方法)或通过Comparator实现将密钥保持在已排序的顺序中你过关了。这两个类别的区别在于第二个类别ConcurrentSkipListMapthread-safe,高度为concurrent

另请参见下表中的迭代顺序列。

  • LinkedHashMap类按原始插入的顺序返回其条目。
  • EnumMap按照定义键的枚举类的顺序返回条目。例如,哪个员工正在覆盖一周中的哪一天(Map< DayOfWeek , Person >)的地图使用Java内置的DayOfWeek枚举类。该枚举的定义是第一个星期一和最后一个星期日。因此,迭代器中的条目将按该顺序显示。

其他六个实现不保证它们报告条目的顺序。

Table listing <code>Map</code> implementations bundled with Java 11, and comparing features of each.

答案 9 :(得分:0)

Steffi Keran答案的现代Java版本

public class Solution {
    public static void main(String[] args) {
        // create a simple hash map and insert some key-value pairs into it
        Map<String, Integer> map = new HashMap<>();
        map.put("Python", 3);
        map.put("C", 0);
        map.put("JavaScript", 4);
        map.put("C++", 1);
        map.put("Golang", 5);
        map.put("Java", 2);
        // Create a linked list from the above map entries
        List<Map.Entry<String, Integer>> list = new LinkedList<>(map.entrySet());
        // sort the linked list using Collections.sort()
        list.sort(Comparator.comparing(Map.Entry::getValue));
        list.forEach(System.out::println);
    }
}