实现Map并保持插入顺序的Java类?

发布于 2024-07-15 11:20:24 字数 643 浏览 5 评论 0原文

我正在java中寻找一个具有键值关联但不使用哈希的类。 这是我当前正在做的事情:

  1. Hashtable 添加值。
  2. 获取 Hashtable.entrySet() 的迭代器。
  3. 迭代所有值并:
    1. 获取迭代器的Map.Entry
    2. 根据值创建 Module 类型的对象(自定义类)。
    3. 将类添加到 JPanel。
  4. 显示面板。

问题是我无法控制取回值的顺序,因此我无法按给定顺序显示值(无需对顺序进行硬编码)。

我将使用 ArrayListVector 来实现此目的,但在代码的后面,我需要获取给定 Key 的 Module 对象,我将其不能使用 ArrayListVector

有谁知道有一个免费/开源的 Java 类可以做到这一点,或者有一种根据添加时间从 Hashtable 中获取值的方法吗?

谢谢!

I'm looking for a class in java that has key-value association, but without using hashes. Here is what I'm currently doing:

  1. Add values to a Hashtable.
  2. Get an iterator for the Hashtable.entrySet().
  3. Iterate through all values and:
    1. Get a Map.Entry for the iterator.
    2. Create an object of type Module (a custom class) based on the value.
    3. Add the class to a JPanel.
  4. Show the panel.

The problem with this is that I do not have control over the order that I get the values back, so I cannot display the values in the a given order (without hard-coding the order).

I would use an ArrayList or Vector for this, but later in the code I need to grab the Module object for a given Key, which I can't do with an ArrayList or Vector.

Does anyone know of a free/open-source Java class that will do this, or a way to get values out of a Hashtable based on when they were added?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

猛虎独行 2024-07-22 11:20:24

我建议 LinkedHashMapTreeMap< /a>. LinkedHashMap 按插入顺序保留键,而 TreeMap 通过 Comparator 或自然的 Comparable< 保持排序/code> 键的顺序。

由于它不必保持元素排序,因此在大多数情况下 LinkedHashMap 应该更快; TreeMap 对于 containsKeygetput 具有 O(log n) 性能根据 Javadocs,remove,而 LinkedHashMap 对于每个操作都是 O(1)

如果您的 API 仅需要可预测的排序顺序,而不是特定的排序顺序,请考虑使用这两个类实现的接口,NavigableMapSortedMap。 这将使您不会将特定的实现泄漏到 API 中,并在之后随意切换到这些特定的类或完全不同的实现。

I suggest a LinkedHashMap or a TreeMap. A LinkedHashMap keeps the keys in the order they were inserted, while a TreeMap is kept sorted via a Comparator or the natural Comparable ordering of the keys.

Since it doesn't have to keep the elements sorted, LinkedHashMap should be faster for most cases; TreeMap has O(log n) performance for containsKey, get, put, and remove, according to the Javadocs, while LinkedHashMap is O(1) for each.

If your API that only expects a predictable sort order, as opposed to a specific sort order, consider using the interfaces these two classes implement, NavigableMap or SortedMap. This will allow you not to leak specific implementations into your API and switch to either of those specific classes or a completely different implementation at will afterwards.

记忆で 2024-07-22 11:20:24

当您迭代映射的 keySet()、entrySet() 或 value() 时,LinkedHashMap 将按照元素插入映射的顺序返回元素。

Map<String, String> map = new LinkedHashMap<String, String>();

map.put("id", "1");
map.put("name", "rohan");
map.put("age", "26");

for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

这将按照元素放入地图的顺序打印元素:

id = 1
name = rohan 
age = 26 

LinkedHashMap will return the elements in the order they were inserted into the map when you iterate over the keySet(), entrySet() or values() of the map.

Map<String, String> map = new LinkedHashMap<String, String>();

map.put("id", "1");
map.put("name", "rohan");
map.put("age", "26");

for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

This will print the elements in the order they were put into the map:

id = 1
name = rohan 
age = 26 
染柒℉ 2024-07-22 11:20:24

如果不可变映射适合您的需求,那么 google 就有一个名为 guava 的库(另请参阅番石榴问题

Guava 提供了一个 ImmutableMap 具有可靠的用户指定的迭代顺序。 此 ImmutableMap 具有containsKey、get 的 O(1) 性能。 显然不支持放置和删除。

ImmutableMap 对象是使用优雅的静态便捷方法 of()copyOf()Builder 对象。

If an immutable map fits your needs then there is a library by google called guava (see also guava questions)

Guava provides an ImmutableMap with reliable user-specified iteration order. This ImmutableMap has O(1) performance for containsKey, get. Obviously put and remove are not supported.

ImmutableMap objects are constructed by using either the elegant static convenience methods of() and copyOf() or a Builder object.

冷…雨湿花 2024-07-22 11:20:24

您可以使用 LinkedHashMap 来控制 Map 中的插入顺序。

Java LinkedHashMap 类的要点是:

  1. 它仅包含唯一元素。

  2. LinkedHashMap 包含基于键的值。

  3. 它可能有一个空键和多个空值。

  4. 与HashMap相同,只是维护插入顺序

    public class LinkedHashMap;   扩展 HashMap   实现 Map  
      

但如果您想使用用户定义的对象或任何原始数据类型键对映射中的值进行排序,那么您应该使用 TreeMap 有关更多信息,请参阅 此链接

You can use LinkedHashMap to main insertion order in Map

The important points about Java LinkedHashMap class are:

  1. It contains only unique elements.

  2. A LinkedHashMap contains values based on the key.

  3. It may have one null key and multiple null values.

  4. It is same as HashMap instead maintains insertion order

    public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> 
    

But if you want sort values in map using User-defined object or any primitive data type key then you should use TreeMap For more information, refer this link

宁愿没拥抱 2024-07-22 11:20:24

您可以维护 Map (用于快速查找)和 List (用于排序),但 LinkedHashMap 可能是最简单的。 您还可以尝试 SortedMap 例如 TreeMap,它具有您指定的任何顺序。

You can maintain a Map (for fast lookup) and List (for order) but a LinkedHashMap may be the simplest. You can also try a SortedMap e.g. TreeMap, which an have any order you specify.

岁月无声 2024-07-22 11:20:24

您可以使用 LinkedHashMap或者您可以实现自己的 CustomMap 来维护插入顺序。

您可以使用具有以下功能的 CustomHashMap

  • 通过在内部使用 LinkedHashMap 来维护插入顺序。
  • 不允许使用 null 或空字符串的键。
  • 一旦创建了具有值的键,我们就不会覆盖它的值。

HashMapLinkedHashMapCustomHashMap

interface CustomMap<K, V> extends Map<K, V> {
    public boolean insertionRule(K key, V value);
}

@SuppressWarnings({ "rawtypes", "unchecked" })
public class CustomHashMap<K, V> implements CustomMap<K, V> {
    private Map<K, V> entryMap;
    // SET: Adds the specified element to this set if it is not already present.
    private Set<K> entrySet;

    public CustomHashMap() {
        super();
        entryMap = new LinkedHashMap<K, V>();
        entrySet = new HashSet();
    }

    @Override
    public boolean insertionRule(K key, V value) {
        // KEY as null and EMPTY String is not allowed.
        if (key == null || (key instanceof String && ((String) key).trim().equals("") ) ) {
            return false;
        }

        // If key already available then, we are not overriding its value.
        if (entrySet.contains(key)) { // Then override its value, but we are not allowing
            return false;
        } else { // Add the entry
            entrySet.add(key);
            entryMap.put(key, value);
            return true;
        }
    }
    public V put(K key, V value) {
        V oldValue = entryMap.get(key);
        insertionRule(key, value);
        return oldValue;
    }
    public void putAll(Map<? extends K, ? extends V> t) {
        for (Iterator i = t.keySet().iterator(); i.hasNext();) {
            K key = (K) i.next();
            insertionRule(key, t.get(key));
        }
    }

    public void clear() {
        entryMap.clear();
        entrySet.clear();
    }
    public boolean containsKey(Object key) {
        return entryMap.containsKey(key);
    }
    public boolean containsValue(Object value) {
        return entryMap.containsValue(value);
    }
    public Set entrySet() {
        return entryMap.entrySet();
    }
    public boolean equals(Object o) {
        return entryMap.equals(o);
    }
    public V get(Object key) {
        return entryMap.get(key);
    }
    public int hashCode() {
        return entryMap.hashCode();
    }
    public boolean isEmpty() {
        return entryMap.isEmpty();
    }
    public Set keySet() {
        return entrySet;
    }
    public V remove(Object key) {
        entrySet.remove(key);
        return entryMap.remove(key);
    }
    public int size() {
        return entryMap.size();
    }
    public Collection values() {
        return entryMap.values();
    }
}

的使用CustomHashMap

public static void main(String[] args) {
    System.out.println("== LinkedHashMap ==");
    Map<Object, String> map2 = new LinkedHashMap<Object, String>();
    addData(map2);

    System.out.println("== CustomHashMap ==");
    Map<Object, String> map = new CustomHashMap<Object, String>();
    addData(map);
}
public static void addData(Map<Object, String> map) {
    map.put(null, "1");
    map.put("name", "Yash");
    map.put("1", "1 - Str");
    map.put("1", "2 - Str"); // Overriding value
    map.put("", "1"); // Empty String
    map.put(" ", "1"); // Empty String
    map.put(1, "Int");
    map.put(null, "2"); // Null

    for (Map.Entry<Object, String> entry : map.entrySet()) {
        System.out.println(entry.getKey() + " = " + entry.getValue());
    }
}

O/P:

== LinkedHashMap == | == CustomHashMap ==
null = 2            | name = Yash
name = Yash         | 1 = 1 - Str
1 = 2 - Str         | 1 = Int
 = 1                |
  = 1               |
1 = Int             |

如果您知道 KEY 是固定的,那么您可以使用 EnumMap。 获取属性/XML 文件 EX 中的值

enum ORACLE {
    IP, URL, USER_NAME, PASSWORD, DB_Name;
}

EnumMap<ORACLE, String> props = new EnumMap<ORACLE, String>(ORACLE.class);
props.put(ORACLE.IP, "127.0.0.1");
props.put(ORACLE.URL, "...");
props.put(ORACLE.USER_NAME, "Scott");
props.put(ORACLE.PASSWORD, "Tiget");
props.put(ORACLE.DB_Name, "MyDB");

Either You can use LinkedHashMap<K, V> or you can implement you own CustomMap which maintains insertion order.

You can use the Following CustomHashMap with the following features:

  • Insertion order is maintained, by using LinkedHashMap internally.
  • Keys with null or empty strings are not allowed.
  • Once key with value is created, we are not overriding its value.

HashMap vs LinkedHashMap vs CustomHashMap

interface CustomMap<K, V> extends Map<K, V> {
    public boolean insertionRule(K key, V value);
}

@SuppressWarnings({ "rawtypes", "unchecked" })
public class CustomHashMap<K, V> implements CustomMap<K, V> {
    private Map<K, V> entryMap;
    // SET: Adds the specified element to this set if it is not already present.
    private Set<K> entrySet;

    public CustomHashMap() {
        super();
        entryMap = new LinkedHashMap<K, V>();
        entrySet = new HashSet();
    }

    @Override
    public boolean insertionRule(K key, V value) {
        // KEY as null and EMPTY String is not allowed.
        if (key == null || (key instanceof String && ((String) key).trim().equals("") ) ) {
            return false;
        }

        // If key already available then, we are not overriding its value.
        if (entrySet.contains(key)) { // Then override its value, but we are not allowing
            return false;
        } else { // Add the entry
            entrySet.add(key);
            entryMap.put(key, value);
            return true;
        }
    }
    public V put(K key, V value) {
        V oldValue = entryMap.get(key);
        insertionRule(key, value);
        return oldValue;
    }
    public void putAll(Map<? extends K, ? extends V> t) {
        for (Iterator i = t.keySet().iterator(); i.hasNext();) {
            K key = (K) i.next();
            insertionRule(key, t.get(key));
        }
    }

    public void clear() {
        entryMap.clear();
        entrySet.clear();
    }
    public boolean containsKey(Object key) {
        return entryMap.containsKey(key);
    }
    public boolean containsValue(Object value) {
        return entryMap.containsValue(value);
    }
    public Set entrySet() {
        return entryMap.entrySet();
    }
    public boolean equals(Object o) {
        return entryMap.equals(o);
    }
    public V get(Object key) {
        return entryMap.get(key);
    }
    public int hashCode() {
        return entryMap.hashCode();
    }
    public boolean isEmpty() {
        return entryMap.isEmpty();
    }
    public Set keySet() {
        return entrySet;
    }
    public V remove(Object key) {
        entrySet.remove(key);
        return entryMap.remove(key);
    }
    public int size() {
        return entryMap.size();
    }
    public Collection values() {
        return entryMap.values();
    }
}

Usage of CustomHashMap:

public static void main(String[] args) {
    System.out.println("== LinkedHashMap ==");
    Map<Object, String> map2 = new LinkedHashMap<Object, String>();
    addData(map2);

    System.out.println("== CustomHashMap ==");
    Map<Object, String> map = new CustomHashMap<Object, String>();
    addData(map);
}
public static void addData(Map<Object, String> map) {
    map.put(null, "1");
    map.put("name", "Yash");
    map.put("1", "1 - Str");
    map.put("1", "2 - Str"); // Overriding value
    map.put("", "1"); // Empty String
    map.put(" ", "1"); // Empty String
    map.put(1, "Int");
    map.put(null, "2"); // Null

    for (Map.Entry<Object, String> entry : map.entrySet()) {
        System.out.println(entry.getKey() + " = " + entry.getValue());
    }
}

O/P:

== LinkedHashMap == | == CustomHashMap ==
null = 2            | name = Yash
name = Yash         | 1 = 1 - Str
1 = 2 - Str         | 1 = Int
 = 1                |
  = 1               |
1 = Int             |

If you know the KEY's are fixed then you can use EnumMap. Get the values form Properties/XML files

EX:

enum ORACLE {
    IP, URL, USER_NAME, PASSWORD, DB_Name;
}

EnumMap<ORACLE, String> props = new EnumMap<ORACLE, String>(ORACLE.class);
props.put(ORACLE.IP, "127.0.0.1");
props.put(ORACLE.URL, "...");
props.put(ORACLE.USER_NAME, "Scott");
props.put(ORACLE.PASSWORD, "Tiget");
props.put(ORACLE.DB_Name, "MyDB");
夕嗳→ 2024-07-22 11:20:24

我不知道它是否是开源的,但经过一番谷歌搜索后,我发现 使用 ArrayList 实现 Map。 它似乎是 1.5 之前的 Java,因此您可能想要对其进行通用化,这应该很容易。 请注意,此实现具有 O(N) 访问权限,但如果您不向 JPanel 添加数百个小部件(无论如何您都不应该这样做),那么这应该不是问题。

I don't know if it is opensource, but after a little googling, I found this implementation of Map using ArrayList. It seems to be pre-1.5 Java, so you might want to genericize it, which should be easy. Note that this implementation has O(N) access, but this shouldn't be a problem if you don't add hundreds of widgets to your JPanel, which you shouldn't anyway.

俏︾媚 2024-07-22 11:20:24

每当我需要维护提前知道的事物的自然顺序时,我都会使用 EnumMap

键将是枚举,您可以按您想要的任何顺序插入,但当您迭代时,它将按枚举顺序(自然顺序)迭代。

此外,当使用 EnumMap 时,不应发生冲突,这样会更有效。

我确实发现使用 enumMap 可以生成干净可读的代码。
这是一个 示例

Whenever i need to maintain the natural order of things that are known ahead of time, i use a EnumMap

the keys will be enums and you can insert in any order you want but when you iterate it will iterate in the enum order (the natural order).

Also when using EnumMap there should be no collisions which can be more efficient.

I really find that using enumMap makes for clean readable code.
Here is an example

故事还在继续 2024-07-22 11:20:24

LinkedHashMap 用于维护插入顺序。 Collections框架的LinkedHashMap类是Map接口的Hashtable和LinkedList实现。 它将其条目存储在哈希表中,并在内部使用双向链表来维护插入顺序。

例如:查找 FirstNonRepeatingCharacter 的 Java 程序。 在下面的示例中,第一个非重复字符是“t”。

代码示例 1:

String str = "Stress";
Chracter ch = str.toLowerCase().chars().mapToObj(c -> Chracter.valueOf((char)c).collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.couting()))).entrySet().stream().filter(entry -> entry.getValue() == 1).map(entry -> entry.getKey()).findFirst().get();

代码示例 2:

String str = "Stress";
Chracter ch = str.toLowerCase().chars().mapToObj(c -> Chracter.valueOf((char)c).collect(Collectors.groupingBy(Function.identity(), Collectors.couting()))).entrySet().stream().filter(entry -> entry.getValue() == 1).map(entry -> entry.getKey()).findFirst().get();

在代码示例 1 中,我使用 LinkedHashMap 来维护插入,从而获得预期结果,而在代码示例 2 中,我们不维护任何插入订单因此失败。

LinkedHashMap is used for maintaing insertion order. The LinkedHashMap class of the Collections framework is the Hashtable and LinkedList implementation of the Map interface. It stores its entries in a Hashtable and uses a doubly-linked list internally to maintain the insertion order.

Ex: Java program to find FirstNonRepeatingCharacter. In the below example first non-repeating character is 't'.

Code Sample 1:

String str = "Stress";
Chracter ch = str.toLowerCase().chars().mapToObj(c -> Chracter.valueOf((char)c).collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.couting()))).entrySet().stream().filter(entry -> entry.getValue() == 1).map(entry -> entry.getKey()).findFirst().get();

Code Sample 2:

String str = "Stress";
Chracter ch = str.toLowerCase().chars().mapToObj(c -> Chracter.valueOf((char)c).collect(Collectors.groupingBy(Function.identity(), Collectors.couting()))).entrySet().stream().filter(entry -> entry.getValue() == 1).map(entry -> entry.getKey()).findFirst().get();

in the code sample 1 I used LinkedHashMap which maintains insertion hence getting the expected result where as in code sample 2 we are not maintaining any insertion order hence it fails.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文