Java 中集合的随机排序?

问题描述 投票:0回答:3

我多次运行此代码(Java 11):

public static void main(String[] args) {
    System.out.println("-----------------------");
    Set<String> elements = Set.of("Neptunium", "Iodine", "Thallium", "Carbon", "Calcium");
    System.out.println(elements);
    elements = elements.stream()
            .map(n -> n.substring(0, 1))
            .collect(Collectors.toSet());

    for (String s : elements) {
        System.out.print(s);
    }
}

结果是:

[Thallium, Carbon, Neptunium, Iodine, Calcium]
CTIN
-----------------------
[Thallium, Calcium, Iodine, Neptunium, Carbon]
CTIN
-----------------------
[Neptunium, Iodine, Calcium, Thallium, Carbon]
CTIN
...

第一组

Set.of("Neptunium", "Iodine", "Thallium", "Carbon", "Calcium");
的顺序是不确定的,正如我所期望的那样。然而第二个
Collectors.toSet()
总是一样的。这是什么魔法?

java set
3个回答
2
投票

Set.of()
没有定义的迭代顺序,并且可能会发生变化。

集合元素的迭代顺序未指定,并且可能会发生变化。

Collectors.toSet()
未定义使用哪个
Set
实现。

public static <T> Collector<T,?,Set<T>> toSet()

返回一个收集器,将输入元素累积到一个新的

Set
中。不保证返回的 Set 的类型、可变性、可序列化性或线程安全性;如果需要对返回的
Set
进行更多控制,请使用
toCollection(Supplier)

目前供应商已硬编码为

HashSet::new
。但未来可能会改变。因此,如果您需要可预测的东西,最好作为供应商传递具体的
Set
实施。因为它当前返回
HashSet
并且您在创建时以相同的顺序传递元素,所以迭代每次都会根据存储桶位置以特定顺序返回数据。这就是为什么结果是一致的。


0
投票

您可以使用

List
来确定元素的顺序,或者如果您需要
Set
,请使用
LinkedHashSet

Set<String> elements = new LinkedHashSet<>(
        List.of("Neptunium", "Iodine", "Thallium", "Carbon", "Calcium"));

0
投票

A

Set
根据定义,没有定义的遭遇顺序。因此,正如正确的aatwork的答案中所解释的,
Set.of
Collectors.toSet
都不会导致任何特定或一致的遭遇顺序。 迭代 Set
 对象时,永远不要期待任何顺序。

SequencedSet

如果您想要按特定顺序排列集合,请使用 Java 21+ 中的

SequencedSet

 接口。

Java 提供了三种实现:

ConcurrentSkipListSet

LinkedHashSet
TreeSet

这是一个使用

Comparable

 对象自然排序的示例。

SequencedSet<String> alphabeticalOrder = new TreeSet<>( List.of( "Neptunium", "Iodine", "Thallium", "Carbon", "Calcium" ) ) ;
或指定 

Comparator

 进行自定义订购。

SequencedSet<String> orderedByLength = new TreeSet<>( Comparator.comparing( String :: length ) ) ; orderedByLength.addAll( List.of( "Neptunium", "Iodine", "Thallium", "Carbon", "Calcium" ) ) ;

NavigableSet

在早期的 Java 中,或者为了获得更多功能,请使用

NavigableSet

 接口及其前身 SortedSet

Java 有两种实现:

ConcurrentSkipListSet

TreeSet

使用方法与上面相同:

NavigableSet<String> alphabeticalOrder = new TreeSet<>( List.of( "Neptunium", "Iodine", "Thallium", "Carbon", "Calcium" ) ) ;
    
© www.soinside.com 2019 - 2024. All rights reserved.