2016-07-12 27 views
2

Gibt es eine Java-Sammlung mit einer Komplexität von O (1) und nicht O (n) für die addAll-Operation, oder muss ich meine eigene Sammlung implementieren? Mit einer effizienten verknüpften Liste sollte die Operation Collection1.addAll (Collection2) die zweite Sammlung an die erste anhängen, indem der erste Knoten von collection2 zum letzten von Sammlung 1 hinzugefügt wird und die anderen folgen. Aber es ist nicht so, dass ich in die Dokumentation lese, es scheint einen Iterator zu benutzen, also denke ich, dass die Komplexität O (collection2.size) ist.Java Collection addAlle Komplexität

Ist das richtig?

+0

http://stackoverflow.com/questions/6540511/time-complexity-for-java-arraylist –

+0

Mai [SO Beitrag sein] (http://stackoverflow.com/questions/559839/big-o-summary -for-java-collections-framework-implementations kann Ihnen helfen. – Sanjeev

+0

danke für die links – Kaizokun

Antwort

3

Auch die Optimierung für verknüpfte Listen funktioniert nur, wenn Sie Elemente von einer verknüpften Liste zu einer anderen verschieben.

Sie könnten eine eigene Art von Sammlung jedoch, die eine weitere Ebene der Indirektion, i. e. enthält eine Sammlung von Sammlungen. Auf diese Weise ist das Hinzufügen einer ganzen Sammlung ziemlich billig und wiederholt sich. Indizierung oder Längenbestimmung kann jedoch sehr teuer werden.

+0

danke natürlich ist es wirklich auf den fall. Für die Längenbestimmung könnte eine einfache Addition der beiden Größen meiner Meinung nach den Job machen. – Kaizokun

+0

@Kaizokun Wenn es nur zwei sind. Vielleicht ist es mehr, wenn Sie diese Klasse mit maximaler Flexibilität gestalten. – glglgl

+0

natürlich jedes Mal, wenn ich eine Sammlung anhängen addiere ich die Größe :) – Kaizokun

2

ArrayList ist wahrscheinlich in dieser Hinsicht so gut wie es geht, aber es hängt auch von der gelieferten Sammlung ab. Die Best-Case-Komplexität ist O (1), aber nur dann, wenn die toArray() Methode der bereitgestellten Collection ebenfalls eine konstante Komplexität aufweist.

Die System.arraycopy() Aufruf, der die tatsächliche Zuteilung tut ist O (1), ohnehin kompliziert ist, siehe unten:

// java.util.ArrayList.addAll 
// Oracle JDK 1.8.0_91 
public boolean addAll(Collection<? extends E> c) { 
    Object[] a = c.toArray(); // O(?) <-- depending on other type 
    int numNew = a.length; 
    ensureCapacityInternal(size + numNew); // Increments modCount 
    System.arraycopy(a, 0, elementData, size, numNew); 
    size += numNew; 
    return numNew != 0; 
} 

Es gibt einige Meinungsverschiedenheiten darüber, ob System.arrayCopy ist eine Konstante Zeitbetrieb . Some say no. Others suggest it is.

Nach to this benchmark I hacked together, es ist irgendwo in der Mitte. Die Copy Times bleibt bis zu 100 Array-Elementen ziemlich konstant, wird aber von da an linear. Ich vermute, dass dort eine Art Paging stattfindet. So effektiv System.arrayCopy hat lineare Zeit Komplexität, es sei denn, die Arrays sind sehr klein.

+0

danke dir, in meinem Fall ist die Sammlung eine verkettete Liste (eine verkettete Liste, ich weiß nicht, wie das in Englisch zu sagen), so dass die toArray Operation ist O (n) ich denke. – Kaizokun

+1

Sind Sie sich sicher? http://stackoverflow.com/questions/7165594/time-complexity-of-system-arraycopy behauptet etwas anderes. Außerdem bin ich mir ziemlich sicher, dass 'sureCapacityInternal' auch in' O (N) 'steht. – fabian

+0

Der erste Teil ist eine Quelle von religiösen Kriegen, wahr. Ich würde argumentieren, dass es aus einer Java-Perspektive eine atomare Operation ist. Es gibt Meinungsverschiedenheiten hier, aber diese Antwort unterstützt meine Theorie: http://stackoverflow.com/a/2772176/342852 –