LinkedHashSet - 插入顺序和重复 - 保持最新 "on top"
LinkedHashSet - insertion order and duplicates - keep newest "on top"
我需要一个保持插入顺序并具有唯一值的集合。 LinkedHashSet 看起来像是要走的路,但有一个问题 - 当两个项目相等时,它会删除最新的一个(这是有道理的),这是一个例子:
set.add("one");
set.add("two");
set.add("three");
set.add("two");
LinkedHashSet
将打印:
one
, two
, three
但我需要的是:
one
, three
, two
最好的解决方案是什么?是否有任何 collection/collections 方法可以做到这一点,或者我应该手动实施它?
初始化 LinkedHashSet 时,您可以重写 add 方法。
Set<String> set = new LinkedHashSet<String>(){
@Override
public boolean add(String s) {
if(contains(s))
remove(s);
return super.add(s);
}
};
现在它给你:
set.add("1");
set.add("2");
set.add("3");
set.add("1");
set.addAll(Collections.singleton("2"));
// [3, 1 ,2]
连 addAll 方法都在工作。
大多数 Java Collections 都可以扩展以进行调整。
子类 LinkedHashSet
, overriding the add
方法。
class TweakedHashSet<T> extends LinkedHashSet<T> {
@Override
public boolean add(T e) {
// Get rid of old one.
boolean wasThere = remove(e);
// Add it.
super.add(e);
// Contract is "true if this set did not already contain the specified element"
return !wasThere;
}
}
你可以简单地使用LinkedHashMap
的一个特殊功能:
Set<String> set = Collections.newSetFromMap(new LinkedHashMap<>(16, 0.75f, true));
set.add("one");
set.add("two");
set.add("three");
set.add("two");
System.out.println(set); // prints [one, three, two]
在 Oracle 的 JRE 中,LinkedHashSet
无论如何都由 LinkedHashMap
支持,因此在功能上没有太大区别,但是这里使用的特殊构造函数配置 LinkedHashMap
以更改顺序每个 access 不仅在 insertion 上。这听起来可能太多了,但实际上只会影响已经包含的键(Set
意义上的值)的插入。返回的 Set
.
未使用其他受影响的 Map
操作(即 get
)
如果您不使用 Java 8,由于类型推断有限,您必须稍微帮助编译器:
Set<String> set
= Collections.newSetFromMap(new LinkedHashMap<String, Boolean>(16, 0.75f, true));
但功能是一样的。
上面提供的所有解决方案都非常好,但如果我们不想覆盖已经实现的集合。我们可以简单地通过一个小技巧使用 ArrayList 来解决这个问题
我们可以创建一个方法,您将使用该方法将数据插入列表
public static <T> void addToList(List<T> list, T element) {
list.remove(element); // Will remove element from list, if list contains it
list.add(element); // Will add element again to the list
}
我们可以调用这个方法来添加元素到我们的列表
List<String> list = new ArrayList<>();
addToList(list, "one");
addToList(list, "two");
addToList(list, "three");
addToList(list, "two");
这里唯一的缺点是我们每次都需要调用我们的自定义方法 addToList()
而不是 list.add()
我需要一个保持插入顺序并具有唯一值的集合。 LinkedHashSet 看起来像是要走的路,但有一个问题 - 当两个项目相等时,它会删除最新的一个(这是有道理的),这是一个例子:
set.add("one");
set.add("two");
set.add("three");
set.add("two");
LinkedHashSet
将打印:
one
,two
,three
但我需要的是:
one
,three
,two
最好的解决方案是什么?是否有任何 collection/collections 方法可以做到这一点,或者我应该手动实施它?
初始化 LinkedHashSet 时,您可以重写 add 方法。
Set<String> set = new LinkedHashSet<String>(){
@Override
public boolean add(String s) {
if(contains(s))
remove(s);
return super.add(s);
}
};
现在它给你:
set.add("1");
set.add("2");
set.add("3");
set.add("1");
set.addAll(Collections.singleton("2"));
// [3, 1 ,2]
连 addAll 方法都在工作。
大多数 Java Collections 都可以扩展以进行调整。
子类 LinkedHashSet
, overriding the add
方法。
class TweakedHashSet<T> extends LinkedHashSet<T> {
@Override
public boolean add(T e) {
// Get rid of old one.
boolean wasThere = remove(e);
// Add it.
super.add(e);
// Contract is "true if this set did not already contain the specified element"
return !wasThere;
}
}
你可以简单地使用LinkedHashMap
的一个特殊功能:
Set<String> set = Collections.newSetFromMap(new LinkedHashMap<>(16, 0.75f, true));
set.add("one");
set.add("two");
set.add("three");
set.add("two");
System.out.println(set); // prints [one, three, two]
在 Oracle 的 JRE 中,LinkedHashSet
无论如何都由 LinkedHashMap
支持,因此在功能上没有太大区别,但是这里使用的特殊构造函数配置 LinkedHashMap
以更改顺序每个 access 不仅在 insertion 上。这听起来可能太多了,但实际上只会影响已经包含的键(Set
意义上的值)的插入。返回的 Set
.
Map
操作(即 get
)
如果您不使用 Java 8,由于类型推断有限,您必须稍微帮助编译器:
Set<String> set
= Collections.newSetFromMap(new LinkedHashMap<String, Boolean>(16, 0.75f, true));
但功能是一样的。
上面提供的所有解决方案都非常好,但如果我们不想覆盖已经实现的集合。我们可以简单地通过一个小技巧使用 ArrayList 来解决这个问题
我们可以创建一个方法,您将使用该方法将数据插入列表
public static <T> void addToList(List<T> list, T element) {
list.remove(element); // Will remove element from list, if list contains it
list.add(element); // Will add element again to the list
}
我们可以调用这个方法来添加元素到我们的列表
List<String> list = new ArrayList<>();
addToList(list, "one");
addToList(list, "two");
addToList(list, "three");
addToList(list, "two");
这里唯一的缺点是我们每次都需要调用我们的自定义方法 addToList()
而不是 list.add()