2017-08-27 59 views
7

生成流元素的认识以便我读该Java 8正式文档:从HashSet的

流可以或可以不具有限定的遭遇顺序。 某个流是否有遇到顺序取决于源和中间操作。某些流源(例如List或 阵列)本质上是有序的,而其他(如HashSet) 则不是。
如果一个流被排序,在同一个源上重复执行相同的 流管道将产生相同的 结果;如果未订购,重复执行可能会产生不同的结果。

试图通过这个代码

public class StreamOrderValidator 
{ 
    public static void main(String[] args) 
    { 
     String[] colors=new String[] {"red","green","blue","orange"}; 
     List<String> colorsList=Arrays.asList(colors); 

     HashSet<String> colorsSet=new HashSet<>(); 
     colorsSet.addAll(colorsList); 
     System.out.println(colorsSet);   // [red, orange, green, blue] 

     List<String> processedColorsSet = processStream(colorsSet.stream()); 
     System.out.println(processedColorsSet); // [RED, ORANGE, GREEN, BLUE] 
    } 

    private static List<String> processStream(Stream<String> colorStream) { 
     List<String> processedColorsList = colorStream.filter(s->s.length()<=6). 
       map(String::toUpperCase).collect(Collectors.toList()); 
     return processedColorsList; 
    } 
} 

理解所提到的行为我跑这个代码许多次,并在所得的流元素的顺序总是相同(显示为注释)。我无法弄清楚这是如何证明上述有关“订单不被保留用于无序集合”的引用文本的理由。

我绝对误解了从javadocs提取的文本。

+0

我相信这里的答案https://stackoverflow.com/questions/29216588/how-to-ens-order-of-processing-in-java8-streams可能只是涵盖你在这里问的问题。 – nullpointer

回答

5

确实在这里有一点误解。 A HashSet或任何Set不是关于订单,除非TreeSet是根据Comparator订购的。

目前,在Java的8一旦你把元素成HashSet(不要改变它) - 会有的元素是如何布局的命令;但是,再次,在你不添加或删除任何它们的条件下。这可以在任何时候改变,所以不要依赖它。

例如运行以下命令:目前有多少次在Java的8

String[] colors = new String[] { "red", "green", "blue", "orange" }; 
List<String> colorsList = Arrays.asList(colors); 

HashSet<String> colorsSet = new HashSet<>(); 
colorsSet.addAll(colorsList); 
System.out.println(colorsSet); 

无论你会总是得到的结果相同:

[red, orange, green, blue] 

但是,一旦你做一些内部重新洗牌:

for (int i = 0; i < 1000; ++i) { 
     colorsSet.add("" + i); 
    } 

    for (int i = 0; i < 1000; ++i) { 
     colorsSet.remove("" + i); 
    } 


    System.out.println(colorsSet); // [blue, red, green, orange] 

您可以看到输出更改,因为Set s没有订单。 要做的关键是没有订单,您确实看到订单不是每次都会发生的保证 - 可能会在java-8中创建一个打破此订单的订单。实际上,用java-9就可以很容易地观察到 - 例如,对于新的Set s,存在随机化模式。

如果你运行这个多次,结果会有所不同:

Set<String> set = Set.of("red", "green", "blue", "orange"); 
System.out.println(set); 

所以,很显然,你stream从这样的Set订单将不能得到保证,因此,你的确会从试验看到不同的结果运行。

4

你所看到的基本上是运气,你正在流传输的HashSet按顺序返回值。如果您随着时间的推移添加了足够的值,您最终会看到来自流的不同结果,因为HashSet的基础HashMap必须调整其自身并重新排序。

你提供的东西(四种颜色)偶然会每次都返回相同的结果,因为不需要底层的HashMap调整自身大小并重新排序值。

铭记一个HashSet由每Java API的文档是一个HashMap,这个问题和它的接受的答案背占地面积你凭借解释一个HashMap的行为看到的:

Order of values retrieved from a HashMap

2

重复执行可能会产生不同的结果。

这里有这个might这个词。即使它不能保证订单,也不意味着订单每次都是随机的。元素根据hashcode放置。 尝试一些不同的值:

String[] colors=new String[] {"5reegdfg","fsdfsd6546","fsdfxvc4","77ggg"}; 
    List<String> colorsList=Arrays.asList(colors); 

    HashSet<String> intSet =new HashSet<>(); 
    intSet.addAll(colorsList); 


    intSet.forEach(e -> System.out.print(e + " ")); 

    System.out.println(); 
    intSet.add("fvcxbxb78ok"); 


    intSet.forEach(e -> System.out.print(e + " ")); 

输出是这样的:

fsdfxvc4 5reegdfg 77ggg fsdfsd6546 
fsdfxvc4 fvcxbxb78ok 5reegdfg 77ggg fsdfsd6546 

正如你所看到的,顺序是在这个例子不同。

+0

我这么认为..对于每个人都不是一个好例子。 Javadocs明确指出:“某些终端操作可能会忽略遇到次序,例如从https://docs.oracle.com/javase/8/docs/api/java/util/stream/package的排序部分获取的forEach() -summary.html。 – user2653926