我想知道是否有人知道删除LinkedHashMap
中重复值的好方法?我有LinkedHashMap
成对的String
和List<String>
。我想删除ArrayList
的重复项。这是为了改善一些下游处理。
我唯一能想到的就是在迭代HashMap
然后遍历ArrayList
时保留已处理值的日志,并检查我之前是否遇到过值。随着列表的增长,这种方法似乎会降低性能。有没有办法预处理HashMap
以删除ArrayList
值中的重复项?
说明......如果我有 String1&gt; List1(a,b,c) String2&gt; List2(c,d,e) 我想删除“c”,因此HashMap中的列表中没有重复项。
答案 0 :(得分:1)
我相信创建第二个HashMap,可以按值排序(按字母顺序,按数字排序),然后对排序列表进行单次扫描,以检查当前节点是否等效于下一个节点,如果它是,删除下一个,并保持增量相同,因此它将保持在该排序列表的相同索引。
或者,当您添加值时,您可以检查它是否已包含此值。
答案 1 :(得分:1)
鉴于你的澄清,你想要这样的东西:
class KeyValue {
public String key;
public Object value;
KeyValue(String key, Object value) {
this.key = key;
this.value = value;
}
public boolean equals(Object o) {
// boilerplate omitted, only use the value field for comparison
}
public int hashCode() {
return value.hashCode();
}
}
public void deduplicate() {
Map<String, List<Object>> items = new HashMap<String, List<Object>>();
Set<KeyValue> kvs = new HashSet<KeyValue>();
for (Map.Entry<String, List<Object>> entry : items.entrySet()) {
String key = entry.getKey();
List<Object> values = entry.getValue();
for (Object value : values) {
kvs.add(new KeyValue(key, value));
}
values.clear();
}
for (KeyValue kv : kvs) {
items.get(kv.key).add(kv.value);
}
}
使用set将删除重复值,KeyValue
允许我们保留原始哈希键。根据需要添加getter和setter或泛型。这也将修改原始地图及其中的列表。我也认为这个的表现应该是O(n)。
答案 2 :(得分:0)
我假设你需要独特的元素(包含在你的列表中)而不是唯一的列表。
如果Map的键和其关联List中的元素之间不需要关联,只需将所有元素分别添加到Set中即可。
如果将所有列表添加到集合中,它将包含唯一的列表对象,而不是列表的唯一元素,因此您必须单独添加元素。
(当然,您可以使用addAll
来简化此操作)
答案 3 :(得分:0)
使用Guava:
Map<Value, Key> uniques = new LinkedHashMap<Value, Key>();
for (Map.Entry<Key, List<Value>> entry : mapWithDups.entrySet()) {
for (Value v : entry.getValue()) {
uniques.put(v, entry.getKey());
}
}
ListMultimap<K, V> uniqueLists = Multimaps.invertFrom(Multimaps.forMap(uniques),
ArrayListMultimap.create());
Map<K, List<V>> uniqueListsMap = (Map) uniqueLists.asMap(); // only if necessary
应该保留值的顺序,并保持它们的唯一性。如果你可以使用ListMultimap<K, V>
来获得你的结果 - 你可能会这样做 - 那就去吧,否则你可能只是将uniqueLists.asMap()
投射到Map<K, List<V>>
(有些滥用泛型,但保证类型安全)。
答案 4 :(得分:0)
所以,澄清......你基本上有K,[V1 ... Vn]并且你想要所有V的唯一值?
public void add( HashMap<String, List> map, HashMap<Objet, String> listObjects, String key, List values)
{
List uniqueValues= new List();
for( int i = 0; i < values.size(); i++ )
{
if( !listObjects.containsKey( values.get(i) ) )
{
listObjects.put( values.get(i), key );
uniqueValues.add( values.get(i) );
}
}
map.put( key, uniqueValues);
}
基本上,我们有另一个HashMap存储列表值,我们在向地图添加列表时删除非唯一的HashMap。这也为您提供了解值的列表所带来的额外好处。
答案 5 :(得分:0)
正如其他人所说,您可以在添加时检查该值,但是,如果您必须在事后执行此操作:
static public void removeDups(Map<String, List<String>> in) {
ArrayList<String> allValues = new ArrayList<String>();
for (List<String> inValue : in.values())
allValues.addAll(inValue);
HashSet<String> uniqueSet = new HashSet<String>(allValues);
for (String unique : uniqueSet)
allValues.remove(unique);
// anything left over was a duplicate
HashSet<String> nonUniqueSet = new HashSet<String>(allValues);
for (List<String> inValue : in.values())
inValue.removeAll(nonUniqueSet);
}
public static void main(String[] args) {
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
map.put("1", new ArrayList(Arrays.asList("a", "b", "c", "a")));
map.put("2", new ArrayList(Arrays.asList("d", "e", "f")));
map.put("3", new ArrayList(Arrays.asList("a", "e")));
System.out.println("Before");
System.out.println(map);
removeDups(map);
System.out.println("After");
System.out.println(map);
}
生成
的输出Before
{3=[a, e], 2=[d, e, f], 1=[a, b, c, a]}
After
{3=[], 2=[d, f], 1=[b, c]}