java 集合保留顺序并且应该是唯一的

java collection to retain order and should be unique

Set<String> stringSet = new HashSet<String>();

显然不会保留订单

Set<String> linkedHastSet = new LinkedHashSet<String>();

在读取上述集合中的元素时,它应该保持顺序,但有时却没有?是我的观察有误还是遗漏了什么?

Javadoc for LinkedHashSet 比较清楚:

the iteration ordering ... is the order in which elements were inserted into the set (insertion-order)

只有 LinkedHashSet 保证可预测的顺序

来自 jdoc:

Hash table and linked list implementation of the Set interface, with predictable iteration order

and should be unique

Set 实现不包含重复元素,如 Java 文档中更详细的解释。

java collection to retain order

"order"是什么意思?

插入顺序:LinkedHashSet

如果您的意思是跟踪对象最初添加到集合中的顺序,请使用 LinkedHashSet

Set< String > colors = new LinkedHashSet<> () ;
String peachPuff = "PeachPuff" ;
colors.add( "CornflowerBlue" ) ;
colors.add( peachPuff ) ;
colors.add( "DarkSlateGray" ) ;
colors.add( peachPuff ) ; // Adding again. Original insertion order maintained.

运行code live at IdeOne.com。请注意 peachPuff 对象如何保持其原始 #2 位置,尽管它已被第二次添加到集合中。

System.out.println( "colors.toString(): " + colors ) ;

colors.toString(): [CornflowerBlue, PeachPuff, DarkSlateGray]

排序顺序:TreeSetConcurrentSkipListSet

如果您的意思是让元素按内容排序,请使用 NavigableSet (successor to SortedSet) 的实现。

排序通过以下任一方式完成:

与 Java 捆绑在一起的两个 class 实现 NavigableSet(和 SortedSet):TreeSetConcurrentSkipListSet

TreeSet

如果您在单个线程内操作集合,或者仅跨线程使用集合进行只读,请使用 TreeSet

示例:

Set< String > names = new TreeSet<> () ;
names.add( "Carol" ) ;
names.add( "Alice" ) ;
names.add( "Bob" ) ;

这将按字母顺序报告。看到这个 code run live at IdeOne.com.

names.toString(): [Alice, Bob, Carol]

ConcurrentSkipListSet

如果跨线程操作集合,concurrency is an issue. Use ConcurrentSkipListSet class。

您可能想了解 skip list 算法。

枚举定义顺序:EnumSet

如果您想跟踪集合枚举对象(请参阅 Tutorial) by the order in which they are defined on the enum, use EnumSet。此 class 针对枚举进行了高度优化,执行速度非常快且使用的内存非常少。

示例:从 DayOfWeek 枚举中跟踪周末。

Set< DayOfWeek > weekend = EnumSet.of( DayOfWeek.SUNDAY , DayOfWeek.SATURDAY ) ;

尽管我们以错误的顺序定义集合,EnumSet 将按照 DayOfWeek 枚举中定义的顺序迭代项目。该顺序是周一至周日,因此我们的 EnumSet 将在周日之前重复周六报告。

看到这个 code run live at IdeOne.com

weekend.toString(): [SATURDAY, SUNDAY]