Java 8 findFirst和Conference顺序

Java 8 findFirst和Conference顺序,java,java-8,Java,Java 8,如果流具有遭遇顺序,则始终返回第一个元素,但是如果流没有遭遇顺序,则可以返回任何元素 我试图演示这在没有遭遇顺序的流上是如何工作的,但是除了实际的第一个元素之外,我无法让它返回任何东西 我尝试将元素添加到未定义遭遇顺序的集合中: Set<String> words = new HashSet<>(); words.addAll(Arrays.asList("this", "is", "a", "stream", "of", "strings"));

如果流具有遭遇顺序,则始终返回第一个元素,但是如果流没有遭遇顺序,则可以返回任何元素

我试图演示这在没有遭遇顺序的流上是如何工作的,但是除了实际的第一个元素之外,我无法让它返回任何东西

我尝试将元素添加到未定义遭遇顺序的
集合中:

    Set<String> words = new HashSet<>();
    words.addAll(Arrays.asList("this", "is", "a", "stream", "of", "strings"));
    Optional<String> firstString = words.stream()
            .findFirst();
    System.out.println(firstString);
我仍然每次都能找回单词
a

然后我尝试使用
BaseStream
中的
unordered
方法,该方法声称返回一个没有遭遇顺序的流,但没有区别:

    firstString = Stream.of("this", "is", "a", "stream", "of", "strings")
            .unordered()
            .findFirst();
    System.out.println(firstString);

现在我每次都会听到这个词。我错过什么了吗?有什么方法可以证明无序流上的
findFirst
返回不同的值吗?

通过将流标记为无序流,实际上您并没有使其成为无序流(您的集合中的顺序没有任何不同),而是删除了有序流可能施加的任何限制

证明这将返回不同结果的方法是使用并行流

 Set<String> words = new HashSet<>();
    words.addAll(Arrays.asList("this", "is", "a", "stream", "of", "strings"));
    Optional<String> firstString = words.stream().parallel()
            .findFirst();
    System.out.println(firstString);
将集合更改为列表并并行运行将保留顺序:

 List<String> words = new ArrayList<>();
    words.addAll(Arrays.asList("this", "is", "a", "stream", "of", "strings"));
    Optional<String> firstString = words.stream().parallel()
            .findFirst();
    System.out.println(firstString); // always Optional[this]
List words=new ArrayList();
addAll(Arrays.asList(“this”、“is”、“a”、“stream”、“of”、“strings”));
可选的firstString=words.stream().parallel()
.findFirst();
System.out.println(第一个字符串);//始终可选[此]

这里必须阅读的绝对值是

,正如@Eugene已经提到的,调用
无序
并不一定会改变元素的实际物理顺序。不要忘记,
unordered
是一个中间操作,在调用终端操作之前,它不会执行任何操作

因此,我倾向于这样想:

  • 当创建一个包含元素
    “this”、“is”、“a”、“stream”、“of”、“strings”
    时,当迭代
    集中的第一个元素是
    “a”
    ,因此
    findFirst
    只返回该值

  • 当您使用
    stream.of(“this”、“is”、“stream”、“of”、“strings”)
    创建流时,它返回一个带有排序限制的流,
    findFirst
    。调用
    unordered
    会删除该限制,但元素
    “this”
    在物理上仍然是第一个元素,因为
    unordered
    不一定会更改源数组中的顺序

  • 一个稍微好一点的例子可能是:

    Set<String> words = new HashSet<>();
    words.addAll(Arrays.asList("this", "is", "stream", "of", "strings"));
    
    Optional<String> firstString1 = words.stream().findFirst();
    // Optional[strings]
    System.out.println(firstString1);
    
    Optional<String> firstString2 = words.stream()
                                         .sorted().findFirst();
    // Optional[is]
    System.out.println(firstString2);
    
    Optional<String> firstString3 = Stream.of("this", "is", "stream", "of", "strings")
                                          .findFirst();
    // Optional[this]
    System.out.println(firstString3);
    
    Optional<String> firstString4 = Stream.of("this", "is", "stream", "of", "strings")
                                          .unordered().findFirst();
    // Optional[this]
    System.out.println(firstString4);
    
    Set words=newhashset();
    addAll(Arrays.asList(“this”、“is”、“stream”、“of”、“strings”));
    可选的firstString1=words.stream().findFirst();
    //可选[字符串]
    System.out.println(firstString1);
    可选的firstString2=words.stream()
    .sorted().findFirst();
    //可选的[是]
    System.out.println(firstString2);
    可选firstString3=Stream.of(“this”、“is”、“Stream”、“of”、“strings”)
    .findFirst();
    //可选[此]
    System.out.println(firstString3);
    可选firstString4=Stream.of(“this”、“is”、“Stream”、“of”、“strings”)
    .unordered().findFirst();
    //可选[此]
    System.out.println(firstString4);
    

    请注意
    sorted()
    方法是如何更改结果的,因为它强制执行排序限制,而
    unordered
    方法没有效果。

    好的,“any”包括“first”的可能性。当然,流实现不会在随机化数据方面浪费精力,因此对于很多情况,尤其是顺序执行,如果我们可以这样称呼它,它仍然是第一个元素(因为没有顺序,就没有可区分的第一个元素)

    对于
    findFirst
    ,显示不同结果的最佳机会是使用并行流。但即便如此,并不是所有的操作组合都适合表现出无序性

    一点是,在当前的实现中,
    findFirst()
    操作在流无序时不会改变其行为,即它不会主动尝试像
    findAny()
    。由于流的来源,它可能仍然表现出不可预测的行为,但是如果您的源是
    流。of(“this”、“is”、“a”、“Stream”、“of”、“strings”)
    ,即一个已知大小的不可变序列,它已经有了可能的最佳并行性能,因此根本无法从链式
    无序()中获益
    ,因此,当前实现不会改变其行为

    这可能会让人惊讶,但在某种程度上,这甚至适用于
    HashSet
    。虽然它有一个未指定的顺序,但在某个时间点它的支持数组中会有一个实际的顺序,并且只要您不修改
    集合
    ,就没有理由对这些条目进行混洗,因此对于特定的
    HashSet
    实例,您可能会重复获得相同的“first”元素,虽然没有指定哪一个,甚至在单个运行时内,但另一个表示相同内容但具有不同历史的
    HashSet
    实例可能具有不同的顺序


    已知可从无序特征中获益的操作的一个示例是
    distinct
    。虽然它必须对重复项进行排序,但如果有显著差异,它必须保持第一个遇到的元素相等。这会显著降低性能,因此,如果流无序,实现将立即尝试获得好处。例如

    List<String> equal=IntStream.range(0, 100)
        .mapToObj(i->new String("test")) // don't do this in normal code
        .collect(Collectors.toList());
    Map<String, Integer> map = IntStream.range(0, equal.size())
        .collect(IdentityHashMap::new, (m,i)->m.put(equal.get(i),i), Map::putAll);
    
    equal.parallelStream().distinct().map(map::get)
         .findFirst().ifPresent(System.out::println);
    
    将打印范围的任意数字,因为我们已发布订购合同,并允许选择任何相等的字符串


    阿尔雷亚
    Set<String> words = new HashSet<>();
    words.addAll(Arrays.asList("this", "is", "stream", "of", "strings"));
    
    Optional<String> firstString1 = words.stream().findFirst();
    // Optional[strings]
    System.out.println(firstString1);
    
    Optional<String> firstString2 = words.stream()
                                         .sorted().findFirst();
    // Optional[is]
    System.out.println(firstString2);
    
    Optional<String> firstString3 = Stream.of("this", "is", "stream", "of", "strings")
                                          .findFirst();
    // Optional[this]
    System.out.println(firstString3);
    
    Optional<String> firstString4 = Stream.of("this", "is", "stream", "of", "strings")
                                          .unordered().findFirst();
    // Optional[this]
    System.out.println(firstString4);
    
    List<String> equal=IntStream.range(0, 100)
        .mapToObj(i->new String("test")) // don't do this in normal code
        .collect(Collectors.toList());
    Map<String, Integer> map = IntStream.range(0, equal.size())
        .collect(IdentityHashMap::new, (m,i)->m.put(equal.get(i),i), Map::putAll);
    
    equal.parallelStream().distinct().map(map::get)
         .findFirst().ifPresent(System.out::println);
    
    equal.parallelStream().unordered().distinct().map(map::get)
         .findFirst().ifPresent(System.out::println);
    
        List<String> wordList = Arrays.asList("this", "is", "a", "stream", "of", "strings");
        Set<String> words = new HashSet<>(wordList);
    
        Set<String> words2 = new HashSet<>(wordList);
        IntStream.range(0, 50).forEachOrdered(i -> words2.add(String.valueOf(i)));
        words2.retainAll(wordList);
    
        System.out.println(words.equals(words2));
        System.out.println(words);
        System.out.println(words2);
    
    true
    [a, strings, stream, of, this, is]
    [this, is, strings, stream, of, a]