Java中的ArrayList是HashMap之后最常用的集合类。 Java ArrayList表示一个可自动调整大小的数组,并用于代替数组。 由于创建数组后我们无法修改数组的大小,因此我们更喜欢在Java中使用ArrayList,一旦数组满了,它就会自动调整大小。 Java中的ArrayList实现List接口,并允许null 。 ArrayList还保持元素的插入顺序,并允许与不允许重复的任何Set实现相反的重复。
ArrayList同时支持Iterator和ListIterator进行迭代,但建议使用ListIterator
因为它允许程序员沿任一方向遍历列表,在迭代过程中修改列表并获取Iterator在列表中的当前位置。 但是,在使用ListIterator时,您无需太小心,因为ListIterator没有当前元素; 它的光标位置始终位于调用previous()
将返回的元素与调用next()
返回的元素之间。 在本Java ArrayList教程中,我们将了解如何创建Java ArrayList并在Java ArrayList上执行各种操作。 在许多Java核心访谈中,诸如ArrayList和Vector之间的差异或LinkedList与ArrayList之类的问题,该集合类也是最受欢迎的。
ArrayList已在Java 5(老虎)中进行了修改,以支持泛型 ,这由于增强的类型安全性而使Java ArrayList更加强大。 在Java5之前,由于没有泛型,因此在编译时不进行类型检查,这意味着有可能在ArrayList中存储不同类型的元素,该元素用于某些目的,并最终在运行时导致ClassCastException 。
使用泛型,您可以创建Java ArrayList,该Java ArrayList仅接受在创建期间指定的对象类型,如果有人尝试将其他任何对象插入Java中的ArrayList,则会导致编译错误。 例如,如果您创建一个String对象的ArrayList,则无法在其上存储Integer,因为ArrayList的add()方法在将对象添加到Java中的ArrayList中之前会检查Type,而Java 1.4的add()
方法接受任何对象。
JDK 1.5中带有泛型的Java ArrayList
同样重要的是要记住, ArrayList不同步,并且不应在多个线程之间共享。 如果多个线程同时访问Java ArrayList实例,并且至少有一个线程在结构上修改列表,则必须在外部对其进行同步。 (根据Java文档,结构修改是添加或删除一个或多个元素或显式调整后备数组大小的任何操作;仅设置元素的值不是结构修改。)
通常,通过在自然封装列表的某个对象上进行同步来完成此操作。 如果不存在这样的对象,则应使用Collections.synchronizedList()
方法“包装”列表。 建议在创建时同步列表,以避免意外的对列表的非同步访问。 另一个更好的选择是使用CopyOnWriteArrayList
,它是从Java 5添加的,并针对多个并发读取进行了优化。 在
CopyOnWriteArrayList
通过创建基础数组的新副本来实现所有可变操作(添加,设置等),这就是为什么将其称为“ CopyOnWrite
”。
Java中的ArrayList示例
让我们看一些用Java创建ArrayList并使用它们的示例 。 我试图提供尽可能多的示例,以说明Java ArrayList上可能的不同操作。 如果您需要其他Java ArrayList示例,请告诉我,我将在此处添加它们。
Java ArrayList示例1:如何创建ArrayList
您可以在Java中使用带有或不带有泛型的ArrayList,因为增强的类型安全性,建议使用泛型版本都允许。
在此示例中,我们将创建一个String的ArrayList。 如果我们尝试除String之外的任何其他对象,则此ArrayList将仅允许String并将引发编译错误。 如果您发现需要在表达式的右侧和左侧指定类型,那么从Java 1.7开始,如果使用菱形运算符(尖括号),则只需要在左侧指定即可。 如果您定义嵌套类型的ArrayList,则可以节省大量空间。
ArrayList<String> stringList = new ArrayList<String> ; // Generic ArrayList to store only String
ArrayList<String> stringList = new ArrayList<>(); // Using Diamond operator from Java 1.7
Java ArrayList示例2:如何将元素添加到ArrayList中
您可以通过调用add()方法将元素添加到ArrayList中。 由于我们使用的是泛型,并且这是String的ArrayList,因此第二行将导致编译错误,因为此ArrayList仅允许使用String元素。
stringList.add("Item"); //no error because we are storing String
stringList.add(new Integer(2)); //compilation error
Java ArrayList示例3:如何查找ArrayList的大小
Java中ArrayList的大小是当前存储在ArrayList中的元素总数。 您可以通过在其上调用size()方法轻松地在ArrayList中找到许多元素。 请记住,这可能与支持ArrayList的数组的长度不同。 实际上,后备数组的长度总是大于ArrayList的大小,以便它可以存储更多元素。
int size = stringList.size();
Java ArrayList示例4:检查Java ArrayList中项目的索引
您可以使用ArrayList the indexOf()
方法来查找特定对象的索引。 使用此方法时,ArrayList在内部使用equals()方法查找对象,因此请确保您的元素实现equals()
和hashCode()
或Object类的默认实现,将使用基于内存位置的对象进行比较。
int index = stringList.indexOf("Item"); //location of Item object in List
如何在循环中从ArrayList检索元素
很多时候,我们需要遍历ArrayList并对每个检索到的项目执行一些操作。 这是不使用Iterator的两种方法。 我们将在下一节中看到Iterator的用法。
for (int i = 0; i < stringList.size(); i++)String item = stringList.get(i);System.out.println("Item " + i + " : " + item);
}From Java5 onwards you can use foreach loop as wellfor(String item: stringList){
System.out.println("retrieved element: " + item);
}
如何在ArrayList中搜索元素?
有时我们需要检查Java的ArrayList中是否存在某个元素,为此,我们可以使用Java的contains()
方法。 contains()
方法采用ArrayList创建中定义的对象类型,如果此列表包含指定的元素,则返回true。 或者,您也可以使用Collections.binarySearch()
方法查看List中是否存在对象。 ArrayList
, Vector
, CopyOnWriteArrayList
和Stack implements
RandomAccess
接口,它们可用于执行二进制搜索。 要了解哪种方法比较好,看到这个文章。
如何在Java中检查ArrayList是否为空
我们可以使用ArrayList的isEmpty()
方法检查它是否为空。 如果此ArrayList不包含任何元素,则isEmpty()
方法返回true。 您还可以使用List的size()
方法检查List是否为空。 如果返回的大小为零,则ArrayList为空。
boolean result = stringList.isEmpty(); //isEmpty() will return true if List is emptyif(stringList.size() == 0){System.out.println("ArrayList is empty");
}
如何从ArrayList中删除元素
有两种方法可以从Java中的ArrayList中删除任何元素 。 您可以根据元素的索引或提供对象本身来删除它。 Remove remove
(int索引)和remove(Object o)
方法用于从Java中的ArrayList中删除任何元素。 由于ArrayList允许重复,因此值得注意的是remove(Object o)
从此列表中删除指定元素的首次出现(如果存在)。 在下面的代码中,第一次调用将从ArrayList中删除第一个元素,而第二次调用将从Java中的ArrayList中删除第一次出现的项。
stringList.remove(0);
stringList.remove(item);
有关从ArrayList删除元素的正确方法的详细讨论,请查看本教程 。
将数据从一个ArrayList复制到另一个ArrayList
为此,您需要多次创建ArrayList的副本,可以使用addAll(Collection c)
Java中ArrayList的方法,用于将ArrayList上的所有元素复制到另一个ArrayList。 下面的代码会将stringList
所有元素添加到新创建的copyOfStringList
。
ArrayList<String> copyOfStringList = new ArrayList<String>();
copyOfStringList.addAll(stringList);
如何替换ArrayList中特定索引处的元素?
您可以使用Java ArrayList的set
( int index
, E element
)方法来替换特定索引中的任何元素。 下面的代码将把stringList
的第一个元素从“ Item
” stringList
为“ Item
Item2
”。
stringList.set(0,"Item2");
如何从ArrayList中删除所有元素?
Java中的ArrayList提供了clear()
方法,该方法从此列表中删除所有元素。 下面的代码将从我们的stringList
所有元素,并使列表为空。 您可以在清除后重新使用Java ArrayList 。
stingList.clear();
如何在Java中从ArrayList转换为Array
ArrayList为您提供了从ArrayList取回阵列的便利 。 您可以使用toArray(T[] a)
方法以适当的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。 “ a
”是要存储列表元素的数组(如果足够大的话); 否则,将为此分配一个具有相同运行时类型的新数组。
String[] itemArray = new String[stringList.size()];
String[] returnedArray = stringList.toArray(itemArray);
如果您想将ArrayList转换回Array,请参见用Java 将数组转换为ArrayList的3种方法
如何在Java中同步ArrayList?
有时,您需要在Java中同步ArrayList以使其在多个线程之间可共享,您可以为此使用Collections实用程序类,如下所示。
List list = Collections.synchronizedList(new ArrayList(...));
尽管也有其他选择,例如,如果您需要同步列表,那么您也可以使用CopyOnWriteArrayList
,它是Java 1.5上添加的并发列表,并且在读取性能方面优于同步ArayList。 您还可以查看本教程,以了解有关如何在Java中同步ArrayList的更多信息?
如何在Java中从Array创建ArrayList?
Java中的ArrayList令人惊奇,您甚至可以从已经存在的数组中创建一个充满元素的ArrayList。 为此,您需要使用Arrays.asList(T... a)
方法,该方法返回由指定数组支持的固定大小的列表。
ArrayList stringList = Arrays.asList(new String[]{"One", "Two", "Three"); //this is not read only List you can still update value of existing elements
如何在Java中循环遍历ArrayList?
您可以使用Iterator或ListIterator 在ArrayList上遍历 。 ListIterator允许您在两个方向上遍历,而Iterator和ListIterator都允许您在遍历时从Java中的ArrayList中删除元素 。
Iterator itr = stringList.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}ListIterator listItr = stringList.listIterator();
while(listItr.hasNext()){
System.out.println(itr.next());
}
请参阅如何在Java中循环ArrayList,以了解在Java中遍历列表的其他两种方法。
如何在Java中对ArrayList进行排序?
您可以使用
Collections.sort(List list)
方法可以按Comparable
接口定义的自然顺序对Java ArrayList进行排序,并且可以使用Collections.sort(List list, Comparator c)
方法根据自定义Comparator对Java ArrayList进行排序。 您还可以查看此帖子, 以在Java中按降序对ArrayList进行排序
如何在Java中将ArrayList转换为HashSet
大多数Collection类都提供一个构造函数,该构造函数接受Collection对象作为参数。 哪个可用于将一个集合的所有元素复制到另一个? HashSet
还提供了可用于将所有对象从ArrayList复制到HashSet
此类构造函数。 但是要小心,因为HashSet
不允许重复,某些对象将不被包括在内,从而导致对象数量减少。 有关分步示例,请参见如何在Java中将ArrayList转换为HashSet 。
有关Java中ArrayList的提示
- ArrayList不是同步的集合,因此不适合在多个线程之间同时使用。 如果要在多线程环境中像数据结构一样使用
ArrayList
,则需要使用新的CopyonWriteArrayList
或使用Collections.synchronizedList()
创建一个同步列表。 前者是并发收集程序包的一部分,并且比第二个程序包具有更高的可伸缩性,但仅在读者多而写少的情况下才有用。 由于每次写操作都会创建一个新的ArrayList
副本,因此如果在大量写操作的环境中使用它,可能会显得过高。 第二个选择是严格同步的集合,就像Vector
或Hashtable
,但是它不可伸缩,因为一旦线程数量急剧增加,争用就成为一个大问题。 - 建议对并发多线程环境使用
CopyOnWriteArrayList
,因为它已针对多个并发读取进行了优化,并为写操作创建了副本。 这是在Tiger(又名JDK 1.5)中添加的。 它是java.util.concurrent
包的一部分,以及ConcurrentHashMap
和BlockingQueue
。 - 当ArrayList满时,它将创建另一个数组,并使用
System.arrayCopy()
将所有元素从一个数组复制到另一个数组。 这是插入需要很多时间的地方。 - Java ArrayList的Iterator和ListIterator都是快速失败的,这意味着如果在创建Iterator之后的任何时间对ArrayList进行结构修改,则除了通过迭代器自己的remove或add方法之外,Iterator都会抛出
ConcurrentModificationException
。 因此,面对并发修改,Iterator会快速干净地失败,这就是为什么将其称为快速失败。 - 不保证
ConcurrentModificationException
,它只是尽力而为。 - 如果要创建同步列表 ,建议在创建基础ArrayList实例的同时创建该列表 ,以防止意外的非同步访问列表。
- 应用程序可以通过使用
ensureCapacity()
操作在添加大量元素之前增加ArrayList实例的容量。 由于ArrayList的增量填充,这可以减少增量重新分配的数量。 -
size()
,isEmpty()
,get()
,set()
,iterator()
和listIterator()
操作在恒定时间内运行, 因为ArrayList基于Array,但是与LinkedList
相比,添加或删除元素的代价LinkedList
。 - Java 1.5中对ArrayList类进行了增强,以支持泛型,该泛型在ArrayList上添加了额外的类型安全性。 建议使用ArrayList的泛型版本,以确保ArrayList仅包含指定的元素类型,并避免任何
ClassCastException
。 - 由于ArrayList实现List接口,因此它保持元素的插入顺序,并且允许重复。
- 如果我们在Java中将ArrayList引用设置为
null
,则ArrayList
所有元素
有资格使用Java进行垃圾收集 ,
前提是不再存在针对这些对象的强大参考。 - 始终使用
isEmpty()
方法检查ArrayList
是否为空,而不是使用size() == 0
检查。 前者更具可读性,如下所示:if(!listOfItems.isEmpty(){System.out.println("Starting order processing); }if(listOfOrders.size() != 0){System.out.println("Order processing started); }Read more: http://javarevisited.blogspot.com/2011/05/example-of-arraylist-in-java-tutorial.html#ixzz3wpLtPwop
- 从Java 5 Tiger起,对
ArrayList
进行了参数设置,您应该始终使用此类的通用版本。 这样可以防止在水果列表中插入鱼或在纸牌列表中插入骰子的经典错误。 使用泛型时,编译器将捕获这些错误。 因此,由于编译器确保正确的对象类型可以从Collection中存储和检索,因此它还可以在运行时防止ClassCastException
。 由于Java编译器会自动添加隐式转换,因此它也消除了手动转换的需要。 对于初学者来说,了解泛型有点棘手,但是值得学习,因为如今没有泛型就没有身体使用集合。
何时在Java中使用ArrayList
现在,您知道什么是ArrayList,此类的不同方法以及其工作方式。 现在是时候学习何时使用ArrayList了。 对于Java程序员来说,了解Collection类非常重要,同样重要的是开发决定在特定情况下使用哪个collection的能力。 大多数时候,两个因素决定着您的决策,性能和功能。
ArrayList是基于索引的数据结构,这意味着如果您知道索引,它就可以提供O(1)
搜索性能;类似地,在最佳情况下向ArrayList中添加元素也是O(1)
性能,但是如果添加会触发列表大小的调整,则它将在O(n)
级别上,因为将花费大量时间将旧列表的元素复制到新的ArrayList中。 回到功能上,如果您适合使用重复的元素,则仅使用此集合类。 它不是线程安全的,所以不要在并发环境中使用它。
翻译自: https://www.javacodegeeks.com/2016/01/10-examples-using-arraylist-java-tutorial.html