前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java集合-List

Java集合-List

作者头像
后端码匠
发布2021-03-16 11:10:08
2.5K0
发布2021-03-16 11:10:08
举报
文章被收录于专栏:后端码匠

Java集合-List

List接口(java.util.List)代表着有序的对象集合, List中包含的元素可以根据它们在List中的内部顺序进行插入、访问、迭代和删除,元素的顺序就是这个数据结构被称为列表的原因。List中的每个元素都有一个索引,第一个元素的索引是0,第二个元素的索引是1。索引的意思是“离List的第一个元素间隔多少个元素”。因为第一个元素在List的开头,所有间隔为0。如果List不是类型化的,使用Java泛型,那么甚至可以在同一个列表中混合不同类型(类)的对象

然而,在时间开发中很少在List中混合不同类型的对象。

List是一个标准的接口,是Collection接口的子类,意味着继承了Collection的特性。

List 和Set

List和Set非常相似,都代表了一组元素的集合,但是也有一些明显的不一样, 这些差异反映在List和Set接口提供的方法中。

第一个不同是List中可以重复添加相同的元素,而Set中只能添加一次。第二个不同是,List中的元素是有顺序的,可以按顺序迭代,Set不会对内部保存的元素的顺序做出任何承诺。

List的实现

作为 Collection 的子类,Collection中的所有方法在List中同样实用。既然List是个接口,所有初始化时需要具体的实现,可以选择下面的List的实现:

  • java.util.ArrayList
  • java.util.LinkedList
  • java.util.Vector
  • java.util.Stack

这些实现中, ArrayList应用最广泛。在java.util.concurrent包中也有List的并发类的实现,更多细节后面的文章会讲述。

创建List

通过List的实现创建List实例,下面是代码:

代码语言:javascript
复制
List listA = new ArrayList();
List listB = new LinkedList();
List listC = new Vector();
List listD = new Stack();

记住,最常用的是ArrayList,其他的实现我们可以根据具体场景使用。

List的泛型

List中默认的是添加Object,但从JAVA5以后增加了泛型,可以让List中添加的元素类型受到限制,下面是代码:

代码语言:javascript
复制
List<MyObject> list = new ArrayList<MyObject>();

List中只能添加 MyObject的实例对象,同时迭代元素时不许强制类型转换,看看下面的代码:

代码语言:javascript
复制
List<MyObject> list = new ArrayList<MyObject>();
 
list.add(new MyObject("First MyObject"));
 
MyObject myObject = list.get(0);
 
for(MyObject anObject : list){
   //do someting to anObject...
}

如果不使用泛型将是下面的样子:

代码语言:javascript
复制
List list = new ArrayList();   //no generic type specified
 
list.add(new MyObject("First MyObject"));
 
MyObject myObject = (MyObject) list.get(0);  //cast needed
 
for(Object anObject : list){
    //cast needed
    MyObject theMyObject = (MyObject) anObject;
 
   //do someting to anObject...
}

注意如何将从列表中检索到的MyObject实例强制转换为MyObject,如果没有设置泛型,编译的时候java只识别Object实例对象,需要强制转换它们的类型。List变量指定泛型是很好得实践,避免了向List中插入错误得类型,能够从List中检索对象,而不必将它们转换为其真实类型, 而且-它帮助代码的读者了解List应该包含什么类型的对象。只有在有充分理由的情况下才应该省略泛型类型。

List中插入元素

可以通过List得add()方法插入元素,下面是代码:

代码语言:javascript
复制
List<String> listA = new ArrayList<>();
 
listA.add("element 1");
listA.add("element 2");
listA.add("element 3");

调用了三次add()方法,增加String到List中。

插入null值

实际是有可能向List中插入null值的,下面是代码:

代码语言:javascript
复制
Object element = null;
 
List<Object> list = new ArrayList<>();
 
list.add(element);

向指定的索引插入元素

可以将元素插入指定索引位置,List有一个add()方法,第一个参数是索引的位置,第二个参数是元素,下面是代码:

代码语言:javascript
复制
list.add(0, "element 4");

如果List中已经包含元素,那么这些元素现在将在列表的内部序列往后退一个序列,比如在插入新元素前索引是0,然后在0的位置在插入一个元素,则原来的元素索引为1。w element was inserted at index 0, will get pushed to index 1 etc.

添加另外一个List的所有元素

可以将一List的所有元素加到另外一个List中,可以使用List的addAll()方法,下面是代码示例:

代码语言:javascript
复制
List<String> listSource = new ArrayList<>();
 
listSource.add("123");
listSource.add("456");
 
List<String> listDest   = new ArrayList<>();
 
listDest.addAll(listSource);

上面例子把listSource 中所有的元素添加到listDest ,

addAll()方法的参数是Collection ,所以可以传入 List 或者Set作为参数,意思就是可以把通过addAll()方法把List或者Set元素加到List中。

从List中获取元素

可以通过 List的索引获取元素,可以用get(int index),下面的代码是通过索引访问List的元素:

代码语言:javascript
复制
List<String> listA = new ArrayList<>();
 
listA.add("element 0");
listA.add("element 1");
listA.add("element 2");
 
//access via index
String element0 = listA.get(0);
String element1 = listA.get(1);
String element3 = listA.get(2);

也可以通过迭代按内部顺序访问List的元素,这个后面会讲述。

查找List中的元素

可以通过List的下面两个方法查找是否包含元素:

  • indexOf()
  • lastIndexOf()
  • indexOf() 方法查找的是给定元素在List中元素第一次出现的索引:
代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
String element1 = "element 1";
String element2 = "element 2";
 
list.add(element1);
list.add(element2);
 
int index1 = list.indexOf(element1);
int index2 = list.indexOf(element2);
 
System.out.println("index1 = " + index1);
System.out.println("index2 = " + index2);

输出结果:

代码语言:javascript
复制
index1 = 0
index2 = 1

查找元素List中最后一个位置

lastIndexOf()方法可以查找元素在List中出现的最后一个索引值,下面是代码:

代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
String element1 = "element 1";
String element2 = "element 2";
 
list.add(element1);
list.add(element2);
list.add(element1);
 
int lastIndex = list.lastIndexOf(element1);
System.out.println("lastIndex = " + lastIndex);

输出结果:

代码语言:javascript
复制
lastIndex = 2

元素“element 1”在List中出现了两次,最后一个位置索引是2(第三个元素)。

检查List中是否包含给定的元素

可以通过 List的contains()方法检查List中是否包含给定的元素:

代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
String element1 = "element 1";
 
list.add(element1);
 
boolean containsElement =
    list.contains("element 1");
 
System.out.println(containsElement);

输出结果:

代码语言:javascript
复制
true

因为List中包含"element 1",为了决定List中是否包含给定的元素,List内部户将要迭代,并且调用equal()方法检查是否与给定的元素相等。既然可以添加null值到List中,那么同样可以检查List中是否包含null值,下面是代码:

代码语言:javascript
复制
list.add(null);
 
containsElement = list.contains(null);
 
System.out.println(containsElement);

显然,如果contains()中传入的是null值,那么contains()内部调用的不是equals()方法而是==。

从List中移除元素

可以通过下面两个方法从List中移除元素:

  • remove(Object element)
  • remove(int index)
  • remove(Object element)移除是List中如果存在的话第一个出现的元素,所有后面的元素前移一个,索引值减1,下面是代码:
代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
String element = "first element";
list.add(element);
 
list.remove(element);

这个例子首先增加了一个元素然后移除,List的 remove(int index)方法是移除给定索引值对应的元素,所有的后面元素往前移动一位,索引值也相应的减1,下面是代码:

代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
list.add("element 0");
list.add("element 1");
list.add("element 2");
 
list.remove(0);

执行完后,List包含 element 1 和 element 2 ,索引值分别是 0 和1。第一个元素 (element 0) 已经被从List中移除。

从List中移除所有元素

List接口包含了clear()方法,这个方法可以移除List中的所有元素。从List中删除所有元素也被称为清除List,下面是代码:

代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
list.add("object 1");
list.add("object 2");
//etc.
 
list.clear();

首先创建List,其次向List中添加两个元素,第三调用clear()方法,调用后List为空。

在List保留给定List中的所有元素

List接口中有个retainAll(),它能够保留一个列表中的所有元素,这些元素也存在于另一个列表中。意思就是,retain()方法移除目标List中在给定的List,中不存在的元素, 就是两个List的交集,下面是代码:

代码语言:javascript
复制
List<String> list      = new ArrayList<>();
List<String> otherList = new ArrayList<>();
 
String element1 = "element 1";
String element2 = "element 2";
String element3 = "element 3";
String element4 = "element 4";
 
list.add(element1);
list.add(element2);
list.add(element3);
 
otherList.add(element1);
otherList.add(element3);
otherList.add(element4);
 
list.retainAll(otherList);

首先创建两个List,然后每个List都新加三个元素,第三步调用list的retainAll()方法参数是otherList , list.retainAll(otherList)执行完后, list中只有 list 和 otherList都有的元素也就是, element1 和element3 。

List大小

可以通过size()获取List的大小,也就是List中元素的个数:

代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
list.add("object 1");
list.add("object 2");
 
int size = list.size();

List的子集

List接口包含一个subList()方法,这个方法可以创建一个原来List的子集。subList()有两个参数:开始索引和结束索引,第一个索引是原List中对应的元素索引,第二个是结束索引,子集中包含起始索引不包括结束索引,和String的substring()非常相似。下面是代码:

代码语言:javascript
复制
List<String> list      = new ArrayList<>();
 
list.add("element 1");
list.add("element 2");
list.add("element 3");
list.add("element 4");
 
List<String> sublist = list.subList(1, 3);

执行完list.subList(1,3)后, sublist will contain the 包含索引为1(第二个)和索引为 2(第三个)元素。记住原来List中半酣四个元素,索引是0到3,调用list.subList(1,3)后将包含索引1,但不包括索引3,因此将元素保留在索引1和索引2处。

List 转换成 Set

可以通过创建啊一个新的Set,然后调用add方法List作为参数,Set会删除List中的重复元素,只保留一个,下面是代码:

代码语言:javascript
复制
List<String> list      = new ArrayList<>();
 
list.add("element 1");
list.add("element 2");
list.add("element 3");
list.add("element 3");
 
Set<String> set = new HashSet<>();
set.addAll(list);

注意 List中element 3添加了两次,Set中包含一次,执行后Set中包含元素 element 1, element 2 和 element 3 。

List转换成数组

可以通过List的 toArray()方法,将List转换成数组:

代码语言:javascript
复制
List<String> list      = new ArrayList<>();
 
list.add("element 1");
list.add("element 2");
list.add("element 3");
list.add("element 3");
 
Object[] objects = list.toArray();

也可以将List转换成指定类型得数组,下面是代码:

代码语言:javascript
复制
List<String> list      = new ArrayList<>();
 
list.add("element 1");
list.add("element 2");
list.add("element 3");
list.add("element 3");
 
String[] objects1 = list.toArray(new String[0]);

注意,即使我们将大小为0的字符串数组传递给toArray(),返回的数组中也会包含List中的所有元素,它将具有与List相同数量的元素。

数组转换成List

同样可以将数组转换成List,下面是代码:

代码语言:javascript
复制
String[] values = new String[]{ "one", "two", "three" };
 
List<String> list = (List<String>) Arrays.asList(values);

Arrays.asList()方法可以将数组转成List。

List排序

可以调用 Collections 的sort()方法给List排序,之前在前面Collections文章中讲到 ,但是下面我会讲述几种方法:

使用Comparable对List排序

如果List中得元素都是实现了Comparable (java.lang.Comparable)接口,那么他们可以自行比较,看下面得代码:

代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
list.add("c");
list.add("b");
list.add("a");
 
Collections.sort(list);

String类实现了 Comparable接口,可以使用Collections 的sort()方法对他们进行自然排序。

使用Comparator对List排序

如果List中的对象元素没有实现Comparable接口,或者想通过其他方式对它们排序而不是用compare()的实现,那么可以实现Comparator (java.util.Comparator)接口。下面是使用Comparator类对Car类型的List排序:

代码语言:javascript
复制
public class Car{
    public String brand;
    public String numberPlate;
    public int noOfDoors;
 
    public Car(String brand, String numberPlate, int noOfDoors) {
        this.brand = brand;
        this.numberPlate = numberPlate;
        this.noOfDoors = noOfDoors;
    }
}

下面代码是对List中的Car对象排序:

代码语言:javascript
复制
List<Car> list = new ArrayList<>();
 
list.add(new Car("Volvo V40" , "XYZ 201845", 5));
list.add(new Car("Citroen C1", "ABC 164521", 4));
list.add(new Car("Dodge Ram" , "KLM 845990", 2));
 
Comparator<Car> carBrandComparator = new Comparator<Car>() {
    @Override
    public int compare(Car car1, Car car2) {
        return car1.brand.compareTo(car2.brand);
    }
};
 
Collections.sort(list, carBrandComparator);

上面是实现 Comparator的例子,实现只是简单的比较了Car的brand属性,也可以再实现Comparator 比较number plates或者门的数量noOfDoors属性, 同样可以使用Lambda表达式实现Comparator,下面是代码示例:

代码语言:javascript
复制
List<Car> list = new ArrayList<>();
 
list.add(new Car("Volvo V40" , "XYZ 201845", 5));
list.add(new Car("Citroen C1", "ABC 164521", 4));
list.add(new Car("Dodge Ram" , "KLM 845990", 2));
 
 
Comparator<Car> carBrandComparatorLambda      =
    (car1, car2) -> car1.brand.compareTo(car2.brand);
 
Comparator<Car> carNumberPlatComparatorLambda =
    (car1, car2) -> car1.numberPlate.compareTo(car2.numberPlate);
 
Comparator<Car> carNoOfDoorsComparatorLambda  =
    (car1, car2) -> car1.noOfDoors - car2.noOfDoors;
 
Collections.sort(list, carBrandComparatorLambda);
Collections.sort(list, carNumberPlatComparatorLambda);
Collections.sort(list, carNoOfDoorsComparatorLambda);

迭代List

可以通过几种不同的方法迭代List:

  • 使用Iterator
  • 使用for-each循环
  • 使用for循环
  • 使用Stream API
  • 使用Iterator迭代List

第一种方法使用Iterator 迭代List,下面是代码:

代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
list.add("first");
list.add("second");
list.add("third");
 
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
    String next = iterator.next();
}

可以调用List的iterator()Iterator,一旦获取了Iterator ,就可以一直调用 hasNext()方法循环直到返回fasle, 调用hasNext()是在while循环中完成的。While内部循环,可以调用Iterator的 next() 方法获取下一个元素。如果List使用了泛型,那么可以在while循环中保存一些对象转换。下面是代码:

代码语言:javascript
复制
List<String> list = new ArrayList<>();
 
list.add("first");
list.add("second");
list.add("third");
    
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
    String obj = iterator.next();
}

使用For-Each循环迭代List

第二种方法For-Each循环是在Java5中引入的,下面是代码:

代码语言:javascript
复制
List list = new ArrayList();
 
list.add("first");
list.add("second");
list.add("third");
 
for(Object element : list) {
    System.out.println(element);
}

for循环对列表中的每个元素执行一次,在for循环中,每个元素依次绑定到obj变量,下面是使用泛型的List迭代:

代码语言:javascript
复制
List<String> list = new ArrayList<String>();
 
//add elements to list
 
for(String element : list) {
    System.out.println(element);
}

注意这人的泛型是String, 因此,可以将for循环中的变量类型设置为String。

使用For循环迭代List

第三种方法是使用标准的for循环迭代:

代码语言:javascript
复制
List list = new ArrayList();
 
list.add("first");
list.add("second");
list.add("third");
    
for(int i=0; i < list.size(); i++) {
    Object element = list.get(i);
}

For循环创建一个int变量,初始值是0,然后循环,直到i的值等于List的大下停止,也就是小于List的大小时一直循环,i的值每次加1,for循环内部可以使用List的get()方法获取元素,下标索引为i。

下面是使用了泛型String:

代码语言:javascript
复制
List<String> list = new ArrayList<String>();
 
list.add("first");
list.add("second");
list.add("third");
    
for(int i=0; i < list.size(); i++) {
    String element = list.get(i);
}

注意此时For循环内部的变量是String,因为List的泛型是String,List中只能包含String对象,因此编译后get()方法返回的是String类型,不需要强制转换。

使用Stream API迭代List

第四种方式是是由Java Stream API迭代List,为了迭代List,需要从List中获取Stream ,可以通过List的 stream()方法获取,下面是代码:

代码语言:javascript
复制
List<String> stringList = new ArrayList<String>();
 
stringList.add("abc");
stringList.add("def");
 
Stream<String> stream = stringList.stream();

最后一行代码调用了List的 stream() 方法,从List中获取了Stream,一旦获取到了Stream,就可以调用Stream的forEach()方法迭代,下面是例子:

代码语言:javascript
复制
List<String> stringList = new ArrayList<String>();
 
stringList.add("one");
stringList.add("two");
stringList.add("three");
 
Stream<String> stream = stringList.stream();
stream
    .forEach( element -> { System.out.println(element); });

调用forEach()方法,将迭代Stream 内部的所有元素,Consumer 为流中的每个元素调用作为参数传递给forEach()方法的使用者,更多的Stream内容后续文章会讲解,或者参考Java Stream API Tutorial.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端码匠 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • List 和Set
  • List的实现
  • 创建List
  • List的泛型
  • List中插入元素
  • 插入null值
  • 向指定的索引插入元素
  • 添加另外一个List的所有元素
  • 从List中获取元素
  • 查找List中的元素
  • 查找元素List中最后一个位置
  • 检查List中是否包含给定的元素
  • 从List中移除元素
  • 从List中移除所有元素
  • 在List保留给定List中的所有元素
  • List大小
  • List的子集
  • List 转换成 Set
  • List转换成数组
  • 数组转换成List
  • List排序
    • 使用Comparable对List排序
      • 使用Comparator对List排序
      • 迭代List
      • 使用For-Each循环迭代List
      • 使用For循环迭代List
      • 使用Stream API迭代List
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档