2017-06-16 71 views
4

如果我從同一個集合創建了2個列表,我可以確定我在這兩個列表中獲得了相同的順序嗎? (我不只要兩個列表具有相同的順序,我不會在這兩個列表之間進行上套的任何操作關心的排序。)java中的集合中的元素的順序

List l = new ArrayList(set); 

List l1 = new ArrayList(set); 

據我所知,有保障的方式創建這些列表並獲得相同的順序,並且我沒有一個很好的理由以這種方式創建兩個列表,但是我想知道爲什麼如果不對其執行任何修改操作,爲什麼集合中元素的排序會發生變化。

編輯:組是無序的HashSet

+1

如果它是一個哈希集,如果它在中間進行了變異,則不會(不保證排序,但不會在沒有修改集的情況下更改)。如果是其他任何東西,排序將被定義,以便您可以基於此進行調整。 – Rogue

+0

這完全取決於實施。我可以想象一個實現,通過遍歷集合會以某種方式改變集合的順序。非常不可能,但可能,並且不能保證它不會發生。 –

+1

編號一個'Set'提供**沒有保證**的迭代順序。甚至不一致。它可以選擇使用你的訪問作爲藉口來整理內部結構,從而改變下一次迭代的順序。 –

回答

5

你會propably得到相同的排序在名單ll1。但由於大多數套都是無序的,所以你沒有保證那將會有相同的順序。

從技術上講,您可以編寫一個Set接口的實現,該接口在每次調用任何方法時都會更改其順序。這仍然會實現界面。

由於在構造new ArrayList(Collection)集合的toArray方法被調用,我們可以看看在Set#toArray()Javadoc

返回一個包含set中所有元素的數組。如果這個集合保證它的迭代器返回它的元素的順序,這個方法必須以相同的順序返回元素。

雖然Set#iterator()的Javadoc說,沒有一般保證:

返回在此set的元素的迭代器。這些元素以特定的順序返回(除非這個集合是某個提供擔保的類的實例)。

鑑於此,我強烈建議您不要依賴於列表的順序。

4

作爲每documentation

公共的ArrayList(集合c)構造的列表包含指定集合的​​元素 ,他們的順序 返回通過集合的迭代器

所以它真的取決於接口實現類Set,如果訂單是恆定的。

例如,如果您使用LinkedHashSet,則迭代順序是可預測的。

+0

我非常確定,目前沒有設置的實現目前由主要實現提供,但這並不意味着它不可能存在。 –

+0

在我的情況下,我使用無序哈希集。 – nahzor

+1

對於HashSet'公共迭代器迭代器()' 將返回此集合中元素的迭代器。元素以特定順序返回。看起來你不能依賴這個訂單。 – MaxZoom

0

有一些結構,其訂單是保證與否。如果我們提到由Java實現的接口Set,則不能保證。最有可能的構造函數ArrayList使用迭代器Set。所以這兩個列表肯定包含總是相同的元素,但順序。這實際上是爲什麼Set使用contains關鍵字而不是find來檢查元素是否存在。

它的子接口SortedSet表示按照某種標準排序的 的集合。在Java 6中,有兩個執行SortedSet的標準 容器。他們是TreeSetConcurrentSkipListSet

除了SortedSet接口之外,還有 LinkedHashSet類。它會記住 元素被插入到集合中的順序,並以 的順序返回其元素。

-2

有一些intertesting和良好的答案在這裏,我可以提出一個解決方案。強加的無序集合像Set期望的(天然的,或其他方式)爲了

List list = new ArrayList(set); 

List secondList = new ArrayList(list); 
0

的一種方式是創建一個有序Set(換言之,一個SortedSet)從給定的集合。如果您的集不是太大,所有你關心是可預知迭代順序,你可以這樣做:

// set = ... 
List<? extends Comparable> list = new TreeSet<>(set).stream().collect(Collectors.toList()); 

這假設集由具有可比性的元素。或者,您可以在TreeSet構造函數中使用自己的比較器。但是,如果元素本身不具有可比性,那麼在創建這樣的比較器時可能會遇到一些問題。