gpt4 book ai didi

java - 我应该使用 Java 中的哪种数据结构以有序形式存储键值对?没有重复项

转载 作者:行者123 更新时间:2023-12-02 00:00:19 25 4
gpt4 key购买 nike

我正在开发一个项目,我需要以有序的方式存储键值对(一对一映射)。然后我应该能够使用值检索键并使用键检索值。我查看了映射、集合和哈希表,但它们没有排序。

此外,虽然微不足道,但如果我们可以 DS 立即检索键和值,即接口(interface)支持此类功能,那就太好了。

编辑:键和值都是唯一的。维持插入的顺序就足够了。

最佳答案

请注意,您没有定义什么算作“已订购”。一个LinkedHashMap允许按插入顺序迭代键(以及值)。相反,TreeMap允许您使用比较器指定排序顺序,并确保添加到 map 的所有项目都按排序顺序存储。 100 次中有 99 次,这些类(class)中的一门就可以满足您的需求。或者,Google 的 Guava项目有几个很不错BiMap您可能会发现适合您需求的实现。

我强烈警告您:如果您认为您需要的内容超出了这些类所能提供的范围,那么您可能会过度设计您的问题。

<小时/>

出于我无法完全证明的原因,我为您实现了一个合适的 UniqueOrderedBiMap,它与 Java Collections 框架兼容,并且所有实现的功能都可以高效运行。您可以使用您认为合适的任何底层映射(如果您确实想要,包括无序映射),并且键和值始终是唯一的。请注意,它是 LinkedHashMap 的一个非常薄包装,因为这就是您所需要的,一个带有额外检查以确保值保持唯一的 LinkedHashMap

对于好奇的人,请检查此答案修订历史记录中的 UniqueOrderedMap ,它缺少 getKey()removeKey() 方法,但更多正确实现了Map接口(interface),并且只需要一个HashSet,而不是一个HashMap来存储已知值。

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class UniqueOrderedBiMap<K, V>implements Map<K, V> {
private Map<K, V> orderedMap;
private HashMap<V, K> valueMap;

public UniqueOrderedBiMap() {
this(new LinkedHashMap<K,V>());
}

public UniqueOrderedBiMap(Map<K, V> underlyingMap) {
orderedMap = underlyingMap;
valueMap = new HashMap<V, K>(orderedMap.size());

for(Map.Entry<K, V> e : orderedMap.entrySet()) {
if(!valueMap.containsKey(e.getValue())) { // Duplicate value
// could instead fail softly by removing the associated item from the map, but this seems cleaner/clearer.
// generally this constructor should be passed an empty map anyways
throw new IllegalArgumentException("Duplicate value "+e.getValue()+" found in underlying map.");
}
valueMap.put(e.getValue(), e.getKey());
}
}

@Override
public int size() {
return orderedMap.size();
}

@Override
public boolean isEmpty() {
return orderedMap.isEmpty();
}

@Override
public boolean containsKey(Object key) {
return orderedMap.containsKey(key);
}

@Override
public boolean containsValue(Object value) {
// more efficient than iterating over the map
return valueMap.containsKey(value);
}

@Override
public V get(Object key) {
return orderedMap.get(key);
}

public K getKey(V value) {
return valueMap.get(value);
}

// Likely want to implement a forcePut(K, V) method like Guava's BiMaps do
@Override
public V put(K key, V value) {
if(valueMap.containsKey(value)) {
throw new IllegalArgumentException("Cannot insert non-unique value "+value);
}
V ret = orderedMap.put(key, value);
valueMap.remove(ret);
valueMap.put(value, key);
return ret;
}

@Override
public V remove(Object key) {
V ret = orderedMap.remove(key);
valueMap.remove(ret);
return ret;
}

public K removeKey(V value) {
K ret = valueMap.remove(value);
orderedMap.remove(ret);
return ret;
}

@Override
public void putAll(Map<? extends K, ? extends V> m) {
// Existing Map implementation's putAll have some optimizations we
// could take advantage of, but this isn't unreasonable for a first pass
for(Entry<? extends K, ? extends V> e : m.entrySet()) {
put(e.getKey(), e.getValue());
}
}

@Override
public void clear() {
orderedMap.clear();
valueMap.clear();
}

@Override
public Set<K> keySet() {
return orderedMap.keySet();
}

@Override
public Collection<V> values() {
return orderedMap.values();
}

@Override
public Set<java.util.Map.Entry<K, V>> entrySet() {
return orderedMap.entrySet();
}

@Override
public boolean equals(Object o) {
if(o instanceof UniqueOrderedBiMap) {
UniqueOrderedBiMap<?,?> map = (UniqueOrderedBiMap<?,?>)o;
return orderedMap.equals(map.orderedMap);
}
return false;
}

@Override
public int hashCode() {
return orderedMap.hashCode();
}

@Override public String toString() {
return orderedMap.toString();
}

public static void main(String[] args) {
String[] names = { "Marcus", "Jim", "Tom", "Sam" };
String[] grades = { "A", "B", "D", "F" };

UniqueOrderedBiMap<String,String> insertionMap = new UniqueOrderedBiMap<>();
UniqueOrderedBiMap<String,String> sortedMap = new UniqueOrderedBiMap<>(new TreeMap<String,String>());

for(int i = 0; i < names.length; i++) {
insertionMap.put(names[i], grades[i]);
sortedMap.put(names[i], grades[i]);
}

// Poor man's assert
System.out.println(insertionMap.toString().equals("{Marcus=A, Jim=B, Tom=D, Sam=F}"));
System.out.println(sortedMap.toString().equals("{Jim=B, Marcus=A, Sam=F, Tom=D}"));

insertionMap.put("Tom", "C");
sortedMap.put("Tom", "C");
System.out.println(insertionMap.toString().equals("{Marcus=A, Jim=B, Tom=C, Sam=F}"));
System.out.println(sortedMap.toString().equals("{Jim=B, Marcus=A, Sam=F, Tom=C}"));

try {
insertionMap.put("Sam", "C");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
try {
sortedMap.put("Sam", "C");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}

insertionMap.remove("Tom");
sortedMap.remove("Tom");
insertionMap.put("Sam", "C");
sortedMap.put("Sam", "C");
System.out.println(insertionMap.toString().equals("{Marcus=A, Jim=B, Sam=C}"));
System.out.println(sortedMap.toString().equals("{Jim=B, Marcus=A, Sam=C}"));

insertionMap.removeKey("A");
sortedMap.removeKey("A");
System.out.println(insertionMap.toString().equals("{Jim=B, Sam=C}"));
System.out.println(sortedMap.toString().equals("{Jim=B, Sam=C}"));
}
}

关于java - 我应该使用 Java 中的哪种数据结构以有序形式存储键值对?没有重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14965788/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com