2017-08-27 82 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