Java Basic TutorialIn der Spalte wird die Sammlungsklasse vorgestellt, die zwei Hauptkategorien umfasst: Karte und Sammlung
Empfohlen (kostenlos): Java Basic Tutorial
Einige fortgeschrittene Programmiersprachen bietet jetzt verschiedene Implementierungen einer vorgefertigten Datenstruktur, wie z. B. das Sammlungsframework der Programmiersprache Java, mit verschiedenen Implementierungen. Die Sammlungsklasse umfasst zwei Hauptkategorien: Karte und Sammlung Sammlung ist die Sammlungsklasse, die wir häufig verwenden. Erstens sind viele Geschäftscodes untrennbar damit verbunden. Werfen wir heute einen Blick auf einige Fallstricke von List.
Wenn wir beispielsweise den folgenden Code ausführen:
List<String> strings = Arrays.asList("m", "g"); strings.add("h");
wird eine java.lang.UnsupportedOperationException</ ausgelöst Code> Ausnahme. Was geht Ihnen zu diesem Zeitpunkt am Herzen? Warum können der zurückgegebenen ArrayList keine Elemente hinzugefügt werden? Können Elemente in Zukunft ordnungsgemäß hinzugefügt werden?
und dann Debug
entscheidend aktivieren Dafa: java.lang.UnsupportedOperationException
异常,此时你内心 OS what?明明返回的 ArrayList 为啥不能往里面增加元素,这以后还能好好的增加元素吗?
,然后果断开启 Debug
大法:
发现返回的 ArrayList
并不是我们常用的 java.util.ArrayList
,而是 Arrays
的内部类 java.util.Arrays.ArrayList
。进入方法 Arrays.asList
源码如下:
public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
方法返回的是 Arrays
的静态内部类 java.util.Arrays.ArrayList
,该类虽然和 java.util.ArrayList
也继承自抽象类 java.util.AbstractList
,但是通过该类的源码发现它并没有对抽象父类AbstractList
的 add
方法默认就是抛出 java.lang.UnsupportedOperationException
异常。
这个坑的根本原因是我们调用返回的 strings
的 add
方法是继承自抽象父类的 add
方法,而抽象父类的方法默认就是抛出 java.lang.UnsupportedOperationException
这个异常。
Arrays.asList
方法除了上面这个 不支持增加、删除元素 这个坑之外,还有另外一个坑:
从以上代码可以发现,对原始数组的修改会影响我们通过 Arrays.asList
方法获得的新 List
,深入 java.util.Arrays.ArrayList
的源码:
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); } ... }
可以发现是直接使用了原始的数组,所有当我们使用 Arrays.asList
方式获得的 List
时要特别注意,因为共享了数组,相互修改时可能产生一些意想不到的 Bug。标准的姿势之一是将其作为 ArrayList
构造方法的参数重新 new
一个 List
出来即可(e.g. List<String> stringList = new ArrayList<>(Arrays.asList(arrays))
)或者通过 Guava
库中的 Lists.newArrayList
,将返回的新 List
和原始的数组解耦,就不会再互相影响了。
在直接遍历集合元素时增加、删除元素会报错,比如执行如下代码:
List<String> stringList = Lists.newArrayList("m", "g", "h"); for (String s : stringList) { if (Arrays.asList("m", "h").contains(s)) { stringList.remove(s); } }
以上代码可以正常编译通过,但是执行时会抛出 java.util.ConcurrentModificationException
异常,查看其源码可以发现,删除元素方法 remove
会使集合结构发生修改,也就是 modCount(
集合实际修改的次数)会修改,在循环过程中,会比较当前 List
的集合实际修改的次数 modCount
与迭代器修改的次数 expectedModCount
,而 expectedModCount
是初始化时的 modCount
, 二者不相等,就会报 ConcurrentModificationException
异常。解决方法主要有两种方式,1.使用 ArrayList
的迭代器方式遍历,然后调用其中的方法。2.在 JDK 1.8+ 可以使用 removeIf
方法进行删除操作。
最后扎心一问:调用 ArrayList
的 remove
方法传入 int
基本类型的数字和 Integer
ArrayList
nicht unsere häufig verwendete java.util.ArrayList
ist, sondern Interne Klasse java.util.Arrays.ArrayList
von Arrays. Geben Sie die Methode Arrays.asList
ein. Der Quellcode lautet wie folgt: Die Methode 🎜rrreee🎜 gibt die statische interne Klasse java.util.Arrays.ArrayList
von Arrays zurück
. Obwohl die Klasse und java.util.ArrayList
auch von der abstrakten Klasse java.util.AbstractList
erben, wird sie über den Quellcode dieser Klasse gefunden dass es keinen Verweis auf die abstrakte übergeordnete Klasse AbstractList
hat. Die Methode add
löst standardmäßig die Ausnahme java.lang.UnsupportedOperationException
aus. 🎜🎜. 🎜🎜Das Die Hauptursache für die Falle besteht darin, dass die add
-Methode der von unserem Aufruf zurückgegebenen strings
von der add
-Methode der abstrakten übergeordneten Klasse geerbt wird und die Methode der abstrakten übergeordneten Klasse. Standardmäßig wird die Ausnahme java.lang.UnsupportedOperationException
ausgelöst. 🎜🎜Die zweite Gefahr besteht darin, dass sich die neue Liste, die von der Arrays.asList-Methode zurückgegeben wird, und die Änderung der ursprünglichen Parametergruppe der Methode gegenseitig beeinflussen 🎜🎜Arrays.asList
-Methode, mit Ausnahme der oben genannten 🎜Tat Das Hinzufügen oder Löschen von Elementen wird nicht unterstützt🎜 Neben dieser Grube gibt es noch eine weitere Grube: 🎜🎜🎜🎜Aus dem obigen Code können wir erkennen, dass Änderungen am ursprünglichen Array Auswirkungen auf die neue Liste
haben, die wir über die Arrays erhalten. asList
-Methode. Gehen Sie tiefer: 🎜rrreee🎜Es kann festgestellt werden, dass das ursprüngliche Array direkt verwendet wird, also wenn wir den Arrays.asList
-Methode zum Abrufen der Liste
Bitte seien Sie besonders vorsichtig, wenn Sie sich gegenseitig ändern, da Arrays gemeinsam genutzt werden und beim gegenseitigen Ändern einige unerwartete Fehler auftreten können. Eine der Standardaktionen besteht darin, es als Parameter des ArrayList
-Konstruktors zu verwenden, um eine Liste
zu neu
(z. B. List<string stringlist="new" arraylist>(Arrays.asList(arrays))</string>
) oder über Lists.newArrayList
in der Guava
-Bibliothek wird der neue verwendet Der zurückgegebene Code>Liste
ist vom ursprünglichen Array entkoppelt und beeinflusst sich nicht mehr gegenseitig. 🎜🎜Die dritte Gefahr besteht darin, dass beim direkten Durchlaufen der Auflistungselemente ein Fehler gemeldet wird. 🎜🎜Beim Hinzufügen oder Löschen von Elementen während der direkten Durchquerung der Auflistungselemente wird beispielsweise ein Fehler gemeldet Der folgende Code: 🎜rrreee🎜Der obige Code kann normal kompiliert werden, aber wenn er ausgeführt wird, tritt eine java.util.ConcurrentModificationException
-Ausnahme auf Die Elementmethode remove
ändert die Sammlungsstruktur, d. h. modCount(
Die tatsächliche Anzahl der Änderungen an der Sammlung) wird während der Schleife geändert zur aktuellen List
-Sammlung modCount
wird mit der Anzahl der Änderungen am Iterator expectedModCount
verglichen, und expectedModCount
ist der modCount
während der Initialisierung. Wenn die beiden nicht gleich sind, wird eine ConcurrentModificationException
-Ausnahme gemeldet. Es gibt zwei Hauptlösungen: 1. Verwenden Sie zum Durchlaufen die Iteratormethode von ArrayList
und rufen Sie dann die darin enthaltenen Methoden auf. 2. In JDK 1.8+ können Sie die Methode removeIf
verwenden, um Löschvorgänge durchzuführen. 🎜🎜Abschließend noch eine herzzerreißende Frage: Rufen Sie die Methode remove
von ArrayList
auf und übergeben Sie die Basistypnummer int
und Integer
Sind die Ausführungsergebnisse der Verpackungstypnummern gleich? 🎜Das obige ist der detaillierte Inhalt vonNotieren Sie die Fallstricke der Java-Sammlungsklassenliste. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!