从Set中删除“第一个”对象

在某些情况下,我需要逐出Java Set最旧的元素。 该集合使用LinkedHashSet实现,这使得这很简单:只需删除set的迭代器返回的第一个元素:

 Set mySet = new LinkedHashSet(); // do stuff... if (mySet.size() >= MAX_SET_SIZE) { Iterator iter = mySet.iterator(); iter.next(); iter.remove(); } 

这很难看:如果我使用的是SortedSet可以用1行做3行(由于其他原因,这里不能选择SortedSet ):

 if (/*stuff*/) { mySet.remove(mySet.first()); } 

那么有没有更简洁的方法, 没有:

  • 更改Set实现,或
  • 写一个静态的实用方法?

利用番石榴的任何解决方案都很好。


我完全清楚套装没有固有的顺序。 我要求删除迭代顺序定义的第一个条目。

LinkedHashSet是LinkedHashMap的包装器,它支持简单的“删除最旧”策略。 要将它用作Set,你可以做到

 Set set = Collections.newSetFromMap(new LinkedHashMap(){ protected boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_ENTRIES; } }); 
 if (!mySet.isEmpty()) mySet.remove(mySet.iterator.next()); 

似乎少于3行。

如果您的集合由多个线程共享,则必须同步它。

如果您确实需要在代码中的多个位置执行此操作,请编写静态方法。

提出的其他解决方案通常较慢,因为它们暗示调用Set.remove(Object)方法而不是Iterator.remove()方法。

 @Nullable public static  T removeFirst(Collection c) { Iterator it = c.iterator(); if (!it.hasNext()) { return null; } T removed = it.next(); it.remove(); return removed; } 

用番石榴:

 if (!set.isEmpty() && set.size() >= MAX_SET_SIZE) { set.remove(Iterables.get(set, 0)); } 

我还建议一种替代方法。 是的,它改变了实现,但没有大幅改变:扩展LinkedHashSet并在add方法中具有该条件:

 public LimitedLinkedHashSet extends LinkedHashSet { public void add(E element) { super.add(element); // your 5-line logic from above or my solution with guava } } 

它仍然是5行,但它使用它的代码是不可见的。 由于这实际上是集合的特定行为,因此将其置于集合中是合乎逻辑的。

我认为你这样做的方式很好。 这是你经常做的事情,值得找一个更短的方法吗? 你可以像这样用Guava做同样的事情:

 Iterables.removeIf(Iterables.limit(mySet, 1), Predicates.alwaysTrue()); 

这增加了包装集合及其迭代器以限制然后再调用alwaysTrue()谓词的小开销……但对我来说似乎并不值得。

编辑:要在答案中添加我在评论中所说的内容,您可以创建一个SetMultimap ,自动限制每个键可以拥有的值的数量,如下所示:

 SetMultimap multimap = Multimaps.newSetMultimap(map, new Supplier>() { public Set get() { return Sets.newSetFromMap(new LinkedHashMap() { @Override protected boolean removeEldestEntry(Entry eldestEntry) { return size() > MAX_SIZE; } }); } }); 

快速而肮脏的单行解决方案: mySet.remove(mySet.toArray(new Foo[mySet.size()])[0]) ;)

但是,我仍然会选择迭代器解决方案,因为这样会更具可读性,也应该更快。

编辑:我会选择Mike Samuel的解决方案。 🙂