Java中的集合1(Collection接口、List接口、List接口的三种实现类、List接口的集合迭代)

  • Post author:
  • Post category:java




集合



集合的概念

​ 首先, 我们来聊一聊数组, 我们知道, 数组是同一类元素的有序集合, 但是数组却又一个致命的缺点, 那就是数组一旦被定义, 那就无法再对其容量进行改变了, 但是我们的开发或者日常生活中, 经常要存储一些可变的数据集合, 这时数组便不能满足我们的需要, 我们就需要一些能够

动态增长长度的容器

来保存我们的数据。而我们需要对数据的保存的各种逻辑可能可能是多种多样的,于是就有了各种各样的数据结构。



Java中对于各种数据结构的实现,就是我们用到的集合



集合API

​ Java的集合类(集合API,集合框架)是Java数据结构的实现,是由很多的接口、抽象类、具体类组成的,都位于java.util包中。

集合的体系图如下:

在这里插入图片描述



Collection接口

​ Collection接口–定义了存取一组对象的方法,其子接口Set和List分别定义了存储方式。

​ Set中的数据对象没有顺序且不可以重复(无序,不重复)。

​ List中的数据对象有顺序且可以重复(有序且重复)。

Collection中定义的集合共有方法:

返回值类型 方法名 功能
boolean add(Object element) 添加元素
boolean addAll(Collection c) 将制定集合的元素添加到此集合中
boolean remove(Object element) 删除指定元素
boolean removeAll(Collection c) 删除指定集合 不包含时,删除相交的元素
void clear() 清空集合
int size() 集合内的元素个数
boolean isEmpty() 判断集合是否为空
boolean contains(Object element) 判断集合中是否包含指定元素
boolean containsAll(Collection c) 判断是否包含某个集合
boolean retainAll(Collection c) 求交集,集合数据发生变化返回true,不变返回false
default boolean removeIf() 条件删除



注意

:这里有一个需要注意的地方,使用其添加方法添加基本数据类型时会默认调用valueof()方法装箱,因为**集合只能存储引用数据类型。**例如:

import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo {
    public static void main(String[] args) {
        Collection data = new ArrayList();
        //集合只能存储引用类型
        data.add("hello!");
        //添加基本类型都会将基本类型装箱为引用类型
        data.add(1);//这里添加1会,将1转换为Integer类型
        data.add("World");
        data.remove(1);
        System.out.println(data);
    }
}

代码示例

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

//Collection中的共有的方法
public class Preview1 {
    public static void main(String[] args) {
        Integer [] arr1 = {1,2,3};
        Collection<Integer> arr = new ArrayList<>(20);
        for (int i = 0; i<15;i++){
            arr.add(i);
        }
        /*
          boolean add(Object element);
          boolean addAll(Collection c);
          boolean remove(Object element);
          boolean removeAll(Collection c);删除指定集合  不包含时,删除相交的元素
          void clear();
          int size();
          boolean isEmpty();
          boolean contains(Object element);
          boolean containsAll(Collection c);
          boolean retainAll(Collection c);   求交集,集合数据发生变化返回true,不变返回false
        */
        System.out.println(arr.add(100));//true
        System.out.println(arr);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 100]
        System.out.println(arr.addAll(Arrays.asList(arr1)));
        System.out.println(arr);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 100, 1, 2, 3]
        System.out.println(arr.remove(1));//[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 100, 1, 2, 3]
        System.out.println(arr);
        System.out.println(arr.removeAll(Arrays.asList(arr1)));
        System.out.println(arr);//[0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 100]
        System.out.println(Arrays.toString(arr1));//[1, 2, 3]
//        arr.clear();
//        System.out.println(arr);//[]
        System.out.println(arr.size());//13
        System.out.println(arr.isEmpty());//false
        System.out.println(arr.contains(10));//true
        System.out.println(arr.containsAll(Arrays.asList(arr1)));//true
        System.out.println(arr.retainAll(Arrays.asList(arr1)));//true
        //removeIf() 条件删除
        System.out.println(arr.removeIf(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer.equals(0);
            }
        }));
        System.out.println(arr);
    }
}



List接口

有序:按照添加顺序排列。

可以有重复元素。

List继承了Collection接口, 有三个实现的类:

​ ArrayList: 数组列表, 数据采用数组方式存储

​ LinkedList: 链表

​ Vector: 数组列表, 添加了同步锁, 线程安全



List接口的常用方法

List接口的方法在它的实现类中都可以使用。(Collection中定义的方法这里都可以使用)

返回值 方法名 功能
void add(Object obj) 将Object类型的元素添加到集合末尾
void add(int index, Object obj) 将Object类型的元素添加到指定位置
void addAll(Collection c) 给集合添加一个新集合,也可以加上位置
void remove(int index) 删除指定位置的元素
void remove(Object obj) 删除指定元素(集合中第一次出现)
void removeAll(Collection c ) 删除指定集合,不包含时删除相交得的元素
set(int index,Object o) 将指定索引的元素替换为指定的元素
get(int index) 返回指定索引位置的元素
boolean contains(Object o) 判断集合中是否包含指定元素
boolean containsAll(Collection c) 判断集合中是否包含指定集合
int indexOf(Object o) 返回指定元素第一次出现的索引值,没有就返回-1
boolean isEmpty() 判断集合是否为空
int lastIndexOf(Object) 返回元素最后一次出现的索引值
int size() 返回此集合的元素数量
List subList(int formIndex,int toIndex) 截取指定区间返回一个集合
void clear( ) 清空集合


asList, toArray(), toArray(T[] a) 的用法

import java.lang.String;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

public class Preview1 {
    private static Object String;

    public static void main(String[] args) {
        String [] arr = {"1","2","3","4"};
        //asList--->Arrays中的方法,可以将一个数组转化为集合
        Collection<String> list = new ArrayList();
        System.out.println(list.addAll(Arrays.asList(arr)));
        System.out.println(list);

        //toArray()--->返回一个类型为Object[]的包含集合中的所有元素的数组
        Object [] arr1 = list.toArray();
        System.out.println(Arrays.toString(arr1));

        //返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型
        String[] arr2 = list.toArray(new String[list.size()]);
        System.out.println(Arrays.toString(arr2));
    }
}

代码示例

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

//List接口的常用方法
public class ListDemo {
     public static void main(String[] args) {
         List list = new LinkedList();
         //添加元素---末尾
         list.add("中");
         list.add(1);
         list.add(true);
         System.out.println(list);
         //添加元素到指定位置
         list.add(1,"风");
         //添加一个新集合
         Collection c = new LinkedList();
         c.add(1);
         c.add(2);
         c.add(3);
         list.addAll(c);
         System.out.println(list);
         //添加一个新集合到指定位置
         list.addAll(2,c);
         System.out.println(list);
        //删除指定位置元素
         list.remove(1);
         System.out.println(list);
         //删除指定元素
         list.remove(1);
         System.out.println(list);
         //修改指定位置元素---返回这个位置之前的元素
         System.out.println(list.set(3,"天"));
         //查询指定位置元素
         System.out.println(list.get(3));
         //判断集合送是否包含指定元素
         System.out.println(list.contains("天"));
         //判断是否包含指定集合
         System.out.println(list.containsAll(c));
         //返回元素第一次出现的索引值,没有就返回-1
         System.out.println(list.indexOf("风"));
         //判断集合是否为空
         System.out.println(list.isEmpty());
         //返回元素最后出现一次的索引值
         System.out.println(list.lastIndexOf(3));
         //返回集合中的元素数量
         System.out.println(list.size());
         //截取集合中的指定区间
         System.out.println(list.subList(2,5));
         //清空集合
         list.clear();
     }
}



实现类:ArrayList

​ ArrayList是实现了长度可变的数组, 在内存中分配连续的空间。

​ **优点:**底层数据结构是数组,查询快,增删慢,遍历元素和随机访问元素的效率高。

​ **缺点:**线程不安全。


ArrayList的常用方法(list接口中的方法在ArrayList中都可用):

返回值 方法名 功能
void ensureCapacity(int minCapacity) 自行增加容量,以保证它最少有指定数量的元素
protected void removeRange(int f,int e) 删除指定区间的元素,需要继承ArrayList才能使用
boolean retainAll(Collection c) 仅保留此集合中在包含指定集合的元素
void trimToSize() 修改当前集合的容量大小为元素个数数量
void sort(比较器) 需要传入一个比较器进行排序

代码示例

import java.util.ArrayList;
import java.util.Comparator;


public class ArrayListDemo extends ArrayList {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        //添加元素---末尾
        list.add("中");
        list.add(1);
        list.add(true);
        System.out.println(list);
        //添加元素到指定位置
        list.add(1, "风");
        //添加一个新集合
        ArrayList c = new ArrayList();
        c.add(1);
        c.add(2);
        c.add(3);
        list.addAll(c);
        System.out.println(list);
        //自行增加容量---让其有最少为指定的容量
        list.ensureCapacity(20);
        //删除指定区间,这是一个受保护权限,需要继承ArrayList才能在子类中调用
        ArrayListDemo list1 = new ArrayListDemo();
                list1.add(0);
                list1.add(1);
                list1.add(2);
                list1.add(3);
                list1.add(4);
                list1.add(5);
        list1.removeRange(1,4);
        System.out.println(list1);
        //仅保留此集合中包含在指定集合中的元素
        list.retainAll(c);
        System.out.println(list);

        //sort 传入一个比较器进行排序
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(3);
        list2.add(7);
        list2.add(5);
        list2.add(0);
        list2.add(1);
        list2.sort(new pd());
        System.out.println(list2);
    }
}

class pd implements Comparator<Integer>{

    @Override
    public int compare(Integer o1, Integer o2) {
        return o1-o2;
    }
} 



实现类:LinkedList

​ LinkedList采用链表存储的方式。插入、删除元素时效率较高。

​ 优点:底层数据结构使用的是链表,查询快、增删慢。

​ 缺点:线程不安全。


LinkedList的常用方法和ArrayList的差不多,也都实现了List接口和Collection接口,底层以链表的形式存储

代码示例

import java.util.*;

public class LinkedListDemo extends LinkedList{
    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        //添加元素---末尾
        list.add("中");
        list.add(1);
        list.add(true);
        System.out.println(list);
        //添加元素到指定位置
        list.add(1,"风");
        //添加一个新集合
        Collection c = new LinkedList();
        c.add(1);
        c.add(2);
        c.add(3);
        list.addAll(c);
        System.out.println(list);
        //添加一个新集合到指定位置
        list.addAll(2,c);
        System.out.println(list);
        //删除指定位置元素
        list.remove(1);
        System.out.println(list);
        //删除指定元素
        list.remove(1);
        System.out.println(list);
        //修改指定位置元素---返回这个位置之前的元素
        System.out.println(list.set(3,"天"));
        //查询指定位置元素
        System.out.println(list.get(3));
        //判断集合送是否包含指定元素
        System.out.println(list.contains("天"));
        //判断是否包含指定集合
        System.out.println(list.containsAll(c));
        //返回元素第一次出现的索引值,没有就返回-1
        System.out.println(list.indexOf("风"));
        //判断集合是否为空
        System.out.println(list.isEmpty());
        //返回元素最后出现一次的索引值
        System.out.println(list.lastIndexOf(3));
        //返回集合中的元素数量
        System.out.println(list.size());
        //截取集合中的指定区间
        System.out.println(list.subList(2,5));
        //删除指定区间,这是一个受保护权限,需要继承ArrayList才能在子类中调用
        LinkedListDemo list1 = new LinkedListDemo();
        list1.add(0);
        list1.add(1);
        list1.add(2);
        list1.add(3);
        list1.add(4);
        list1.add(5);
        list1.removeRange(1,4);
        System.out.println(list1);
        //sort 传入一个比较器进行排序
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(3);
        list2.add(7);
        list2.add(5);
        list2.add(0);
        list2.add(1);
        list2.sort(new pd());
        System.out.println(list2);
    }
}
class pd implements Comparator<Integer> {

    @Override
    public int compare(Integer o1, Integer o2) {
        return o1-o2;
    }
}



实现类:Vector

​ Vector底层实现就是数组,和ArrayList是一致的,但是Vector添加了同步锁synchronized,保证了线程安全。



效率测试

测试ArrayList和LinkedList的存入和查找效率

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;

//测试ArrayList和LinkedList存,查效率
public class Test1 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        Date date1 = new Date();
        for (int i = 0; i < 10000; i++) {
            list.add("a");
        }
        for (int i = 0; i < 90000; i++) {
            list.add(2500,"a");
        }
        Date date2 = new Date();
        System.out.println("ArrayList存10万次的时间:"+(date2.getTime()-date1.getTime()));
        //        ArrayList存10万次的时间:521ms
        Date date3 = new Date();
        for (int i = 0; i < 100000; i++) {
            list.get(2500);
        }
        Date date4 = new Date();
        System.out.println("ArrayList查10万次的时间:"+(date4.getTime()-date3.getTime()));
        //ArrayList查10万次的时间:0ms

        LinkedList list1 = new LinkedList();
        Date date5 = new Date();
        for (int i = 0; i < 10000; i++) {
            list1.add("a");
        }
        for (int i = 0; i < 90000; i++) {
            list1.add(2500,"a");
        }
        Date date6 = new Date();
        System.out.println("LinkedList存10万次的时间:"+(date6.getTime()-date5.getTime()));
        //LinkedList存10万次的时间:399ms
        Date date7 = new Date();
        for (int i = 0; i < 100000; i++) {
            list1.get(2500);
        }
        Date date8 = new Date();
        System.out.println("LinkedList查10万次的时间:"+(date8.getTime()-date7.getTime()));
        //LinkedList查10万次的时间:401ms
    }
}



List接口的迭代



for循环

​ 语法格式:for(int i;i < list.size() ; i++){…}



注意:

for循环有一个缺陷,就是在删除元素的时候,集合的长度会变小,但是索引 i 的值却在不断变大,这就会出现删不尽的情况,因此我们总是需要做一些小小的处理,请看代码。

代码示例

import java.util.ArrayList;

//遍历数组--for循环
public class ForDemo {
    public static void main(String[] args) {
        ArrayList<String> arr = new ArrayList<>();
        arr.add("a");
        arr.add("s");
        arr.add("d");
        arr.add("e");
        arr.add("s");
        System.out.println(arr);

        for (int i = 0; i < arr.size(); i++) {
            System.out.println(arr.get(i));
        }

        //删除元素后,集合的长度也发生了变化,但是索引 i 的值一直在变大,会出现删不尽的情况
        for (int i = 0; i < arr.size(); i++) {
            arr.remove(i);
            //使用 i-- 将i的值不断变小,等于说每一次都在删除敌意个数
            i--;
        }
        System.out.println(arr);//[s, e]
    }



增强for循环

​ 语法格式:for(Object obj:list){System. out. println(obj);}

​ **注意:**增强for循环,不允许在遍历的时候对元素进行操作,否则会抛出异常,但是我们可以进行一次操作,比如删除一个元素后立刻break,趁着jvm还没反应过来抛出异常时,我们就跳出去。

代码示例

import java.util.ArrayList;

//迭代---增强for循环
public class ForeachDemo {
    public static void main(String[] args) {
        ArrayList<String> arr = new ArrayList<>();
        arr.add("a");
        arr.add("s");
        arr.add("d");
        arr.add("e");
        arr.add("s");
        System.out.println(arr);

        for (String s: arr) {
            System.out.println(s);
        }
        //增强for循环,不允许遍历时对元素进行操作,否则会报错:ConcurrentModificationException
        //但是可以进行一次操作,比如删除已次元素后,趁着异常还没抛出时立刻跳出
        for (String s: arr) {
            arr.remove(s);
            break;
        }
        System.out.println(arr);//[s, d, e, s]
    }
}



迭代器–iterator

​ 这是Collection接口中提供的操作,直接上代码:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Preview2 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");

         Iterator<String> iterator = arr.iterator();
            //hasNext() 检测迭代器中是否还有元素
            while(iterator.hasNext()){
            //每次都从arr中拿出一个元素
                String s = iterator.next();
                if (s.equals("c")){
            //这里不能使用原本的集合对象,因为迭代器中不能直接调用集合对象,需要使用iterator作为中间人
                    iterator.remove();
                }
            }
        System.out.println(arr);
    }
}



版权声明:本文为Lotus_dong原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。