Java Language
Sammlungen
Suche…
Einführung
Das Collections-Framework in java.util
bietet eine Reihe generischer Klassen für Datensätze mit Funktionen, die von regulären Arrays nicht bereitgestellt werden können.
Collections Framework enthält Schnittstellen für Collection<O>
mit den Haupt-Subschnittstellen List<O>
und Set<O>
und der Mapping-Collection Map<K,V>
. Collections sind die Root-Schnittstelle und werden von vielen anderen Collection-Frameworks implementiert.
Bemerkungen
Sammlungen sind Objekte, in denen Sammlungen anderer Objekte gespeichert werden können. Sie können den Typ der in einer Sammlung gespeicherten Daten mit Generics angeben.
Sammlungen verwenden im Allgemeinen die Namespaces java.util
oder java.util.concurrent
.
Java 1.4.2 und folgende unterstützen keine Generics. Daher können Sie nicht die Typparameter angeben, die eine Auflistung enthält. Abgesehen von der Typensicherheit müssen Sie auch Casts verwenden, um den korrekten Typ aus einer Sammlung zurückzuholen.
Neben Collection<E>
gibt es mehrere Haupttypen von Collections, von denen einige Untertypen haben.
-
List<E>
ist eine geordnete Sammlung von Objekten. Es ähnelt einem Array, definiert jedoch keine Größenbegrenzung. Implementierungen werden normalerweise intern größer, um neuen Elementen Rechnung zu tragen. -
Set<E>
ist eine Sammlung von Objekten, die keine Duplikate zulässt.-
SortedSet<E>
ist einSet<E>
, das auch die Elementreihenfolge angibt.
-
-
Map<K,V>
ist eine Sammlung von Schlüssel / Wert-Paaren.-
SortedMap<K,V>
ist eineMap<K,V>
, in der auch die Elementreihenfolge angegeben ist.
-
Java 5 fügt einen neuen Sammlungstyp hinzu:
-
Queue<E>
ist eine Sammlung von Elementen, die in einer bestimmten Reihenfolge verarbeitet werden sollen. Die Implementierung gibt an, ob dies FIFO oder LIFO ist. Dies macht dieStack
Klasse überflüssig.
Java 6 fügt einige neue Untertypen von Sammlungen hinzu.
-
NavigableSet<E>
ist einSet<E>
mit integrierten Navigationsmethoden. -
NavigableMap<K,V>
ist eineMap<K,V>
mit integrierten Navigationsmethoden. -
Deque<E>
ist eineQueue<E>
, die von beiden Enden gelesen werden kann.
Beachten Sie, dass die obigen Elemente alle Schnittstellen sind. Um sie verwenden zu können, müssen Sie die entsprechenden implementierenden Klassen wie ArrayList
, HashSet
, HashMap
oder PriorityQueue
.
Für jeden Auflistungstyp gibt es mehrere Implementierungen mit unterschiedlichen Leistungskennzahlen und Anwendungsfällen.
Beachten Sie, dass das Liskov-Substitutionsprinzip für die Erfassungsuntertypen gilt. Das heißt, ein SortedSet<E>
kann an eine Funktion übergeben werden, die ein Set<E>
erwartet. Weitere Informationen zur Verwendung von Auflistungen mit Klassenvererbung finden Sie auch im Abschnitt Generics über Bounded Parameters .
Wenn Sie eigene Sammlungen erstellen möchten, kann es einfacher sein, eine der abstrakten Klassen (z. B. AbstractList
) zu erben, anstatt die Schnittstelle zu implementieren.
Vor 1.2 mussten Sie stattdessen die folgenden Klassen / Schnittstellen verwenden:
-
Vector
stattArrayList
-
Dictionary
anstelle vonMap
. Beachten Sie, dass das Wörterbuch auch eine abstrakte Klasse und keine Schnittstelle ist. -
Hashtable
stattHashMap
Diese Klassen sind veraltet und sollten in modernem Code nicht verwendet werden.
ArrayList deklarieren und Objekte hinzufügen
Wir können eine ArrayList
erstellen (nach der List
Schnittstelle):
List aListOfFruits = new ArrayList();
List<String> aListOfFruits = new ArrayList<String>();
List<String> aListOfFruits = new ArrayList<>();
Verwenden Sie nun die Methode add
, um einen String
hinzuzufügen:
aListOfFruits.add("Melon");
aListOfFruits.add("Strawberry");
Im obigen Beispiel enthält die ArrayList
den String
"Melon" an Index 0 und den String
"Strawberry" an Index 1.
Wir können auch mehrere Elemente mit der addAll(Collection<? extends E> c)
-Methode hinzufügen
List<String> aListOfFruitsAndVeggies = new ArrayList<String>();
aListOfFruitsAndVeggies.add("Onion");
aListOfFruitsAndVeggies.addAll(aListOfFruits);
Jetzt ist "Onion" bei aListOfFruitsAndVeggies
auf 0 aListOfFruitsAndVeggies
, "Melon" bei Index 1 und "Strawberry" bei Index 2.
Erstellen von Sammlungen aus vorhandenen Daten
Standardsammlungen
Java Collections-Framework
Eine einfache Methode zum Arrays.asList
einer List
aus einzelnen Datenwerten besteht in der Verwendung der java.utils.Arrays
Methode Arrays.asList
:
List<String> data = Arrays.asList("ab", "bc", "cd", "ab", "bc", "cd");
Alle Standardimplementierungsimplementierungen stellen Konstruktoren bereit, die eine andere Collection als Argument verwenden und der neuen Collection zum Zeitpunkt der Konstruktion alle Elemente hinzufügen:
List<String> list = new ArrayList<>(data); // will add data as is
Set<String> set1 = new HashSet<>(data); // will add data keeping only unique values
SortedSet<String> set2 = new TreeSet<>(data); // will add data keeping unique values and sorting
Set<String> set3 = new LinkedHashSet<>(data); // will add data keeping only unique values and preserving the original order
Google Guava Collections-Framework
Ein weiteres großartiges Framework ist Google Guava
, das eine erstaunliche Google Guava
ist (mit praktischen statischen Methoden) zum Erstellen verschiedener Typen von Standardsammlungen. Lists
und Sets
:
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
...
List<String> list1 = Lists.newArrayList("ab", "bc", "cd");
List<String> list2 = Lists.newArrayList(data);
Set<String> set4 = Sets.newHashSet(data);
SortedSet<String> set5 = Sets.newTreeSet("bc", "cd", "ab", "bc", "cd");
Mapping-Sammlungen
Java Collections-Framework
In ähnlicher Weise kann für Karten bei einer Map<String, Object> map
eine neue Karte mit allen Elementen wie folgt erstellt werden:
Map<String, Object> map1 = new HashMap<>(map);
SortedMap<String, Object> map2 = new TreeMap<>(map);
Apache Commons Collections Framework
Mit Apache Commons
Sie Map mit Array in ArrayUtils.toMap
sowie MapUtils.toMap
:
import org.apache.commons.lang3.ArrayUtils;
...
// Taken from org.apache.commons.lang.ArrayUtils#toMap JavaDoc
// Create a Map mapping colors.
Map colorMap = MapUtils.toMap(new String[][] {{
{"RED", "#FF0000"},
{"GREEN", "#00FF00"},
{"BLUE", "#0000FF"}});
Jedes Element des Arrays muss entweder ein Map.Entry oder ein Array sein, das mindestens zwei Elemente enthält, wobei das erste Element als Schlüssel und das zweite als Wert verwendet wird.
Google Guava Collections-Framework
Dienstprogrammklasse aus dem Google Guava
Framework heißt Maps
:
import com.google.common.collect.Maps;
...
void howToCreateMapsMethod(Function<? super K,V> valueFunction,
Iterable<K> keys1,
Set<K> keys2,
SortedSet<K> keys3) {
ImmutableMap<K, V> map1 = toMap(keys1, valueFunction); // Immutable copy
Map<K, V> map2 = asMap(keys2, valueFunction); // Live Map view
SortedMap<K, V> map3 = toMap(keys3, valueFunction); // Live Map view
}
Stream
,
Stream.of("xyz", "abc").collect(Collectors.toList());
oder
Arrays.stream("xyz", "abc").collect(Collectors.toList());
Listen beitreten
Die folgenden Möglichkeiten können zum Verbinden von Listen verwendet werden, ohne die Quellliste (n) zu ändern.
Erste Ansatz. Hat mehr Zeilen aber leicht verständlich
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
Zweiter Ansatz. Hat eine Zeile weniger aber weniger lesbar.
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
Dritter Ansatz. Erfordert die Bibliothek von Drittanbieter- Apache-Commons-Collections .
ListUtils.union(listOne,listTwo);
Bei Verwendung von Streams kann das gleiche durch erreicht werden
List<String> newList = Stream.concat(listOne.stream(), listTwo.stream()).collect(Collectors.toList());
Verweise. Schnittstellenliste
Elemente aus einer Liste innerhalb einer Schleife entfernen
Es ist schwierig, Elemente aus einer Liste zu entfernen, wenn sie sich innerhalb einer Schleife befinden. Dies liegt daran, dass der Index und die Länge der Liste geändert werden.
In Anbetracht der folgenden Liste werden hier einige Beispiele aufgeführt, die zu einem unerwarteten Ergebnis führen, und einige, die zu einem korrekten Ergebnis führen.
List<String> fruits = new ArrayList<String>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Strawberry");
FALSCH
In Iteration von for
Überspringen "Banane" entfernen :
Das Codebeispiel druckt nur Apple
und Strawberry
. Banana
wird übersprungen , da es zum Index bewegt 0
einmal von Apple
gelöscht wird, aber zur gleichen Zeit i
zu erhöht wird 1
.
for (int i = 0; i < fruits.size(); i++) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
}
}
Entfernen in der erweiterten for
Anweisung Throws Exception:
Wegen der Iteration über die Sammlung und deren gleichzeitige Änderung.
Löst aus: java.util.ConcurrentModificationException
for (String fruit : fruits) {
System.out.println(fruit);
if ("Apple".equals(fruit)) {
fruits.remove(fruit);
}
}
RICHTIG
While-Schleife mit einem Iterator
entfernen
Iterator<String> fruitIterator = fruits.iterator();
while(fruitIterator.hasNext()) {
String fruit = fruitIterator.next();
System.out.println(fruit);
if ("Apple".equals(fruit)) {
fruitIterator.remove();
}
}
Die Iterator
Schnittstelle verfügt nur für diesen Fall über eine remove()
Methode. Diese Methode ist jedoch in der Dokumentation als "optional" markiert und kann eine UnsupportedOperationException
.
Löst aus: UnsupportedOperationException - wenn der Entfernungsvorgang von diesem Iterator nicht unterstützt wird
Es ist daher ratsam, die Dokumentation zu überprüfen, um sicherzustellen, dass diese Operation unterstützt wird (in der Praxis, sofern es sich nicht um eine unveränderliche Sammlung handelt, die über eine Bibliothek eines Drittanbieters erhalten wird, oder wenn eine der Methoden Collections.unmodifiable...()
verwendet wird. Die Operation wird fast immer unterstützt.
Während der Verwendung eines Iterator
eine ConcurrentModificationException
ausgelöst, wenn der modCount
der List
der modCount
des Iterator
geändert wird. Dies kann in demselben Thread oder in einer Multithread-Anwendung geschehen, die dieselbe Liste verwendet.
Ein modCount
ist eine int
Variable, die zählt, wie oft diese Liste strukturell geändert wurde. Eine strukturelle Änderung bedeutet im Wesentlichen, dass eine add()
oder remove()
Operation für das Collection
Objekt aufgerufen wird (von Iterator
vorgenommene Änderungen werden nicht gezählt). Wenn der Iterator
erstellt wird, speichert er diesen modCount
und prüft bei jeder Iteration der List
, ob der aktuelle modCount
ist und wann der Iterator
erstellt wurde. Wenn der modCount
Wert modCount
wird, wird eine ConcurrentModificationException
modCount
.
Für die oben deklarierte Liste wird eine Operation wie folgt keine Ausnahme auslösen:
Iterator<String> fruitIterator = fruits.iterator();
fruits.set(0, "Watermelon");
while(fruitIterator.hasNext()){
System.out.println(fruitIterator.next());
}
Iterator
jedoch nach der Initialisierung eines Iterator
ein neues Element zur List
hinzufügen, wird eine ConcurrentModificationException
:
Iterator<String> fruitIterator = fruits.iterator();
fruits.add("Watermelon");
while(fruitIterator.hasNext()){
System.out.println(fruitIterator.next()); //ConcurrentModificationException here
}
Rückwärts iterieren
for (int i = (fruits.size() - 1); i >=0; i--) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
}
}
Dies überspringt nichts. Der Nachteil dieses Ansatzes ist, dass die Ausgabe umgekehrt ist. In den meisten Fällen, in denen Sie Elemente entfernen, spielt dies jedoch keine Rolle. Sie sollten dies niemals mit LinkedList
tun.
Iterieren vorwärts, Anpassen des Schleifenindex
for (int i = 0; i < fruits.size(); i++) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
i--;
}
}
Dies überspringt nichts. Wenn das i
te Element aus der List
, wird das ursprünglich beim Index i+1
positionierte Element zum neuen i
ten Element. Daher kann die Schleife i
dekrementieren, damit die nächste Iteration das nächste Element verarbeiten kann, ohne zu überspringen.
Verwenden einer Liste "Sollte entfernt werden"
ArrayList shouldBeRemoved = new ArrayList();
for (String str : currentArrayList) {
if (condition) {
shouldBeRemoved.add(str);
}
}
currentArrayList.removeAll(shouldBeRemoved);
Mit dieser Lösung kann der Entwickler überprüfen, ob die korrekten Elemente sauberer entfernt wurden.
In Java 8 sind folgende Alternativen möglich. Diese sind sauberer und unkomplizierter, wenn das Entfernen nicht in einer Schleife erfolgen muss.
Stream filtern
Eine List
kann gestreamt und gefiltert werden. Mit einem geeigneten Filter können Sie alle unerwünschten Elemente entfernen.
List<String> filteredList =
fruits.stream().filter(p -> !"Apple".equals(p)).collect(Collectors.toList());
Beachten Sie, dass im Gegensatz zu allen anderen Beispielen hier, in diesem Beispiel eine neue produziert List
Instanz und hält die ursprüngliche List
unverändert.
removeIf
Spart den Aufwand für das Erstellen eines Streams, wenn nur ein Satz von Elementen entfernt werden muss.
fruits.removeIf(p -> "Apple".equals(p));
Unveränderbare Sammlung
Manchmal ist es nicht ratsam, eine interne Sammlung offenzulegen, da dies aufgrund seiner veränderlichen Eigenschaft zu einer Sicherheitsanfälligkeit durch schädlichen Code führen kann. Um "schreibgeschützte" Sammlungen bereitzustellen, stellt java seine unveränderlichen Versionen zur Verfügung.
Eine nicht veränderbare Sammlung ist oft eine Kopie einer veränderbaren Sammlung, die garantiert, dass die Sammlung selbst nicht geändert werden kann. Versuche, es zu ändern, führen zu einer Ausnahme für die Ausnahme "UnsupportedOperationException".
Es ist wichtig zu beachten, dass Objekte, die sich in der Sammlung befinden, noch geändert werden können.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyPojoClass {
private List<Integer> intList = new ArrayList<>();
public void addValueToIntList(Integer value){
intList.add(value);
}
public List<Integer> getIntList() {
return Collections.unmodifiableList(intList);
}
}
Der folgende Versuch, eine nicht veränderbare Sammlung zu ändern, löst eine Ausnahme aus:
import java.util.List;
public class App {
public static void main(String[] args) {
MyPojoClass pojo = new MyPojoClass();
pojo.addValueToIntList(42);
List<Integer> list = pojo.getIntList();
list.add(69);
}
}
Ausgabe:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055)
at App.main(App.java:12)
Iteration über Sammlungen
Iteration über Liste
List<String> names = new ArrayList<>(Arrays.asList("Clementine", "Duran", "Mike"));
names.forEach(System.out::println);
Wenn wir Parallelität brauchen, verwenden Sie
names.parallelStream().forEach(System.out::println);
for (String name : names) {
System.out.println(name);
}
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
//Creates ListIterator which supports both forward as well as backward traversel
ListIterator<String> listIterator = names.listIterator();
//Iterates list in forward direction
while(listIterator.hasNext()){
System.out.println(listIterator.next());
}
//Iterates list in backward direction once reaches the last element from above iterator in forward direction
while(listIterator.hasPrevious()){
System.out.println(listIterator.previous());
}
Iteration über Set
Set<String> names = new HashSet<>(Arrays.asList("Clementine", "Duran", "Mike"));
names.forEach(System.out::println);
for (Iterator<String> iterator = names.iterator(); iterator.hasNext(); ) {
System.out.println(iterator.next());
}
for (String name : names) {
System.out.println(name);
}
Iterator iterator = names.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
Iteration über Map
Map<Integer, String> names = new HashMap<>();
names.put(1, "Clementine");
names.put(2, "Duran");
names.put(3, "Mike");
names.forEach((key, value) -> System.out.println("Key: " + key + " Value: " + value));
for (Map.Entry<Integer, String> entry : names.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
// Iterating over only keys
for (Integer key : names.keySet()) {
System.out.println(key);
}
// Iterating over only values
for (String value : names.values()) {
System.out.println(value);
}
Iterator entries = names.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
Unveränderliche leere Sammlungen
Manchmal ist es angebracht, eine unveränderliche leere Sammlung zu verwenden. Die Collections
Klasse stellt Methoden bereit, um solche Sammlungen auf effiziente Weise abzurufen:
List<String> anEmptyList = Collections.emptyList();
Map<Integer, Date> anEmptyMap = Collections.emptyMap();
Set<Number> anEmptySet = Collections.emptySet();
Diese Methoden sind generisch und konvertieren die zurückgegebene Sammlung automatisch in den Typ, dem sie zugewiesen ist. Das heißt, ein Aufruf von zB emptyList()
kann auf jede Art von zugeordnet werden List
und ebenfalls für emptySet()
und emptyMap()
.
Die von diesen Methoden zurückgegebenen Auflistungen sind unveränderlich, da sie UnsupportedOperationException UnsupportedOperationException
wenn Sie versuchen, Methoden aufzurufen, die ihren Inhalt ändern ( add
, put
usw.). Diese Auflistungen sind in erster Linie als Ersatz für leere Methodenergebnisse oder andere Standardwerte nützlich, anstatt null
oder Objekte mit new
erstellen.
Sammlungen und Grundwerte
Sammlungen in Java funktionieren nur für Objekte. Dh es gibt keine Map<int, int>
in Java. Stattdessen müssen primitive Werte in Objekte verpackt werden, wie in der Map<Integer, Integer>
. Java-Auto-Boxing ermöglicht die transparente Verwendung dieser Sammlungen:
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 17); // Automatic boxing of int to Integer objects
int a = map.get(1); // Automatic unboxing.
Leider ist der Aufwand erheblich . Eine HashMap<Integer, Integer>
erfordert etwa 72 Bytes pro Eintrag (z. B. bei 64-Bit-JVM mit komprimierten Zeigern und unter Annahme von Ganzzahlen größer als 256 und einer Belastung von 50% der Map). Da die tatsächlichen Daten nur 8 Byte umfassen, führt dies zu einem erheblichen Overhead. Darüber hinaus erfordert es zwei Ebenen der Indirektion (Karte -> Eintrag -> Wert), es ist unnötig langsam.
Es gibt mehrere Bibliotheken mit optimierten Sammlungen für primitive Datentypen (die nur ~ 16 Bytes pro Eintrag bei 50% Last erfordern, dh 4x weniger Speicher und eine Ebene der Dereferenzierung weniger) Werte in Java.
Übereinstimmende Elemente mit Iterator aus Listen entfernen.
Oben habe ich ein Beispiel zum Entfernen von Elementen aus einer Liste innerhalb einer Schleife bemerkt und ich dachte an ein anderes Beispiel, das diesmal mit Hilfe der Iterator
Schnittstelle nützlich sein könnte.
Dies ist eine Demonstration eines Tricks, der hilfreich sein kann, wenn Sie doppelte Elemente in Listen behandeln, die Sie entfernen möchten.
Hinweis: Dies wird nur zum Entfernen von Elementen aus einer Liste innerhalb eines Schleifenbeispiels hinzugefügt:
Definieren wir also unsere Listen wie gewohnt
String[] names = {"James","Smith","Sonny","Huckle","Berry","Finn","Allan"};
List<String> nameList = new ArrayList<>();
//Create a List from an Array
nameList.addAll(Arrays.asList(names));
String[] removeNames = {"Sonny","Huckle","Berry"};
List<String> removeNameList = new ArrayList<>();
//Create a List from an Array
removeNameList.addAll(Arrays.asList(removeNames));
Die folgende Methode nimmt zwei Collection-Objekte auf und führt den Zauber aus, die Elemente in unserer removeNameList
entfernen, die mit Elementen in nameList
.
private static void removeNames(Collection<String> collection1, Collection<String> collection2) {
//get Iterator.
Iterator<String> iterator = collection1.iterator();
//Loop while collection has items
while(iterator.hasNext()){
if (collection2.contains(iterator.next()))
iterator.remove(); //remove the current Name or Item
}
}
Aufrufen der Methode und Übergeben der nameList
und der removeNameList
wie folgt: removeNames(nameList,removeNameList);
Erzeugt die folgende Ausgabe:
Array-Liste vor dem Entfernen von Namen: James Smith Sonny Huckle Berry Finn Allan
Array-Liste nach dem Entfernen von Namen: James Smith Finn Allan
Eine einfache, übersichtliche Verwendung für Sammlungen, die sich als nützlich erweisen, um sich wiederholende Elemente in Listen zu entfernen.
Erstellen Sie Ihre eigene Iterable-Struktur für die Verwendung mit Iterator oder für jede Schleife.
Um sicherzustellen, dass unsere Sammlung mithilfe eines Iterators oder für jede Schleife wiederholt werden kann, müssen wir die folgenden Schritte ausführen:
- Das, worauf wir iterieren wollen, muss
Iterable
undIterable
iterator()
Iterable
. - Entwerfen Sie einen
java.util.Iterator
indem SiehasNext()
,next()
undremove()
überschreiben.
Ich habe unten eine einfache generische Liste für verknüpfte Listen hinzugefügt, die die oben genannten Entitäten verwendet, um die verknüpfte Liste iterierbar zu machen.
package org.algorithms.linkedlist;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class LinkedList<T> implements Iterable<T> {
Node<T> head, current;
private static class Node<T> {
T data;
Node<T> next;
Node(T data) {
this.data = data;
}
}
public LinkedList(T data) {
head = new Node<>(data);
}
public Iterator<T> iterator() {
return new LinkedListIterator();
}
private class LinkedListIterator implements Iterator<T> {
Node<T> node = head;
@Override
public boolean hasNext() {
return node != null;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
Node<T> prevNode = node;
node = node.next;
return prevNode.data;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Removal logic not implemented.");
}
}
public void add(T data) {
Node current = head;
while (current.next != null)
current = current.next;
current.next = new Node<>(data);
}
}
class App {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>(1);
list.add(2);
list.add(4);
list.add(3);
//Test #1
System.out.println("using Iterator:");
Iterator<Integer> itr = list.iterator();
while (itr.hasNext()) {
Integer i = itr.next();
System.out.print(i + " ");
}
//Test #2
System.out.println("\n\nusing for-each:");
for (Integer data : list) {
System.out.print(data + " ");
}
}
}
Ausgabe
using Iterator:
1 2 4 3
using for-each:
1 2 4 3
Dies wird in Java 7+ ausgeführt. Sie können es auch auf Java 5 und Java 6 ausführen, indem Sie Folgendes ersetzen:
LinkedList<Integer> list = new LinkedList<>(1);
mit
LinkedList<Integer> list = new LinkedList<Integer>(1);
oder einfach jede andere Version durch Einfügen der kompatiblen Änderungen.
Pitfall: Ausnahmen für gleichzeitige Änderungen
Diese Ausnahme tritt auf, wenn eine Auflistung geändert wird, während sie mit anderen Methoden als den vom Iterator-Objekt bereitgestellten Methoden durchlaufen wird. Wir haben zum Beispiel eine Liste von Hüten und möchten alle entfernen, die über Ohrenklappen verfügen:
List<IHat> hats = new ArrayList<>();
hats.add(new Ushanka()); // that one has ear flaps
hats.add(new Fedora());
hats.add(new Sombrero());
for (IHat hat : hats) {
if (hat.hasEarFlaps()) {
hats.remove(hat);
}
}
Wenn wir diesen Code ausführen, wird ConcurrentModificationException ausgelöst, da der Code die Auflistung ändert, während er durchlaufen wird. Die gleiche Ausnahme kann auftreten, wenn einer der mehreren Threads, die mit derselben Liste arbeiten, versucht, die Auflistung zu ändern, während andere iterieren. Das gleichzeitige Ändern von Sammlungen in mehreren Threads ist eine natürliche Sache, sollte jedoch mit den üblichen Werkzeugen aus der Toolbox für gleichzeitige Programmierung behandelt werden, z. B. Synchronisationssperren, spezielle Sammlungen, die für die gleichzeitige Änderung übernommen wurden, und die geklonte Sammlung von der ursprünglichen Konfiguration abändern.
Untersammlungen
Liste subList (int fromIndex, int bisIndex)
FromIndex ist hier inklusive und toIndex ist exklusiv.
List list = new ArrayList();
List list1 = list.subList(fromIndex,toIndex);
- Wenn die Liste nicht im gegebenen Bereich vorhanden ist, wird IndexOutofBoundException ausgelöst.
- Alle Änderungen, die an list1 vorgenommen wurden, wirken sich auf dieselben Änderungen in der Liste aus. Dies wird als gesicherte Sammlungen bezeichnet.
- Wenn der fromnIndex größer ist als der toIndex (fromIndex> bisIndex), wird IllegalArgumentException ausgelöst.
Beispiel:
List<String> list = new ArrayList<String>();
List<String> list = new ArrayList<String>();
list.add("Hello1");
list.add("Hello2");
System.out.println("Before Sublist "+list);
List<String> list2 = list.subList(0, 1);
list2.add("Hello3");
System.out.println("After sublist changes "+list);
Ausgabe:
Vor der Unterliste [Hello1, Hello2]
Nach Unterlistenänderungen [Hello1, Hello3, Hello2]
Teilmenge festlegen (fromIndex, toIndex)
FromIndex ist hier inklusive und toIndex ist exklusiv.
Set set = new TreeSet();
Set set1 = set.subSet(fromIndex,toIndex);
Der zurückgegebene Satz löst eine IllegalArgumentException aus, wenn versucht wird, ein Element außerhalb seines Bereichs einzufügen.
Map subMap (vonKey, toKey)
fromKey ist inklusive und toKey ist exklusiv
Map map = new TreeMap();
Map map1 = map.get(fromKey,toKey);
Wenn fromKey größer als toKey ist oder wenn diese Map selbst einen eingeschränkten Bereich hat und fromKey oder toKey außerhalb der Grenzen des Bereichs liegt, wird IllegalArgumentException ausgelöst.
Alle Sammlungen unterstützen gesicherte Sammlungen, dh Änderungen, die an der Untersammlung vorgenommen wurden, haben dieselben Änderungen an der Hauptsammlung.