15.Collection集合接口、泛型、List接口及其实现类

1、集合概述

集合和数组的区别:

  • 长度不同
    • 数组一旦初始化长度不能改变
    • 集合是可以改变的
  • 元素类型不同
    • 数组既可以存储基本数据类型元素,也可以存储引用数据类型元素
    • 集合只能存储引用数据类型元素=

集合的体系结构:

  • 单列集合:Collection接口(单个)
    • List接口(元素有序且可重复):ArrayList类、LinkedList类、Vector类
    • Set接口(元素无序且不可重复):HashSet类、LinkedHashSet类、TreeSet类
  • 多列集合:Map接口(KV键值对)
    • HashMap类、LinkedHashMap类、TreeMap类、HashTable类、Properties类

1.1 Collection接口

  • 特点:它是“单列集合”的顶级接口。
  • 位置:java.util
  • 方法:
  1. boolean add(E e)

    确保此 collection 包含指定的元素(可选操作)。

  2. void clear()

    移除此 collection 中的所有元素(可选操作)。

  3. boolean contains(Object o)

    如果此 collection 包含指定的元素,则返回 true。

  4. boolean isEmpty()

    如果此 collection 不包含元素,则返回 true。

  5. Iterator iterator()

    返回在此 collection 的元素上进行迭代的迭代器。

  6. boolean remove(Object o)

    从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。

  7. int size()

    返回此 collection 中的元素数。

1.2 Collection集合的面试题

  • 多态调用方法的特点:

    先看父类或者父接口中是否含有这个方法,如果有执行子类或者实现类重写后的方法;如果没有编译报错

使用多态创建Collection实现类对象,在打印对象名时,其实就是隐式调用对象的toString(),既然如此,调用toString()也满足多态调用方法的特点,先看Collection接口中是否含有toString(),通过查看源码发现Collection接口及其父接口中并没有toString(),所以代码应该编译报错,但是实际上编译没有报错,而且这个多态形式的对象也可以显示调用toString(),为什么?

  • 原因:

    java中所有接口都隐式继承Object类的接口形式或者说Java中所有的接口里面都隐式包含Object类中实例方法的抽象形式

public class CollectionDemo03 {
	public static void main(String[] args) {
		//使用多态的方式创建Collection集合实现类对象
		Collection coll = new ArrayList();

		//添加元素
		coll.add("abc");
		coll.add("def");
		coll.add("ghi");

		System.out.println(coll.toString());
	}
}

1.3 Iterator迭代器

  • 格式:
Collection coll = new ArrayList();
Iterator it = coll.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}
  • 迭代器的注意事项:

    1. 使用迭代器进行迭代器集合时,只能迭代一次,如果想二次使用,需要重新获取迭代器对象
    2. 在使用迭代器的过程中,不能针对集合中的元素或者集合的长度做任何更改,否则会发生并发修改异常ConcurrentModificationException

1.4 增强for(JDK5.0)

  • 原理:其实就是前面讲解的"迭代器"操作的简化版

  • 格式:

    for (集合元素的数据类型 对象名 : 容器名) {
    	
    }
    
  • 增强for的注意事项

  1. 在使用增强for的过程中,不能针对集合中的元素或者集合的长度做任何更改,否则会发生并发修改异常ConcurrentModificationException

  2. 增强for除了可以遍历集合,也可以遍历数组,但是在实际开发中不推荐使用增强for遍历数组

    原因:

    效率低,增强for的底层是迭代器,迭代器又是集合所特有,通过增强for遍历数组,是先将数组转换为集合,再由集合获取迭代器对象进行遍历。尤其是基本数据类型数组,是先将基本数据类型数组转换为存储对应包装类型的数组,再由存储包装类型的数组转换为存储包装类型的集合,通过集合获取迭代器对象进行遍历。

1.5 Stream流

public static void main(String[] args) {
    Collection coll = new ArrayList();
    //添加元素
    coll.add("abc");
    coll.add("def");
    coll.add("ghi");
    //获取流对象
    Stream stream = coll.stream();
    stream.forEach(System.out::println);
}

2、泛型

  • 定义:未知的,没有确定的数据类型

  • 声明格式

    <未知数据类型的名>英文大写

  • 声明内容

    可以在声明的时候进行声明泛型

    可以在声明接口的时候进行声明泛型

    可以在声明方法的时候进行声明泛型

  • 好处

    将程序逻辑处理提前到编译时期,可以通过泛型给集合指定存储类型,如果不是该类型的话,编译报错

2.1 含有泛型的类

  • 声明格式:

    public class 类名<泛型> {
    }
    
  • 注意事项:

    在使用含有泛型的类的时候,需要给该泛型进行确认,如果不明确,JVM明确为Object类型

  • 明确时机:

    创建该类对象时

2.2 含有泛型的接口

  • 声明格式:

    public interface 接口名<泛型> {
    
    }
    
  • 注意事项:

    在使用含有泛型的接口的时候,需要给该泛型进行确认,如果不明确,JVM明确为Object类型

  • 明确时机:

    创建该接口的实现类对象时

2.3 含有泛型的方法

  • 声明格式:

    修饰符 <泛型> 返回值类型 方法名 () {}
    
  • 注意事项:

    在使用含有泛型的方法的时候,需要给该泛型进行确认

  • 明确时机:

    调用方法进行传递参数时

public class MyList<AT> {
	public void add (AT at) {
		System.out.println("添加元素");
	}
    public <AGG> AGG method (AGG agg) {
        System.out.println(agg.getClass().getName());
        return null;
    }
}
public class CollectionDemo10 {
    public static void main(String[] args) {
        MyList<String> myList = new MyList<>();
        myList.add("123");
        myList.method(new Integer(1));
    }
}

2.4 泛型的高级应用

2.4.1 泛型的通配符

  • 含义:对含有泛型的方法的简化

  • 前提条件:方法的形参是含有泛型的类或者接口类型

  • 声明格式:

    • 泛型普通格式使用:

      修饰符 <泛型> 返回值类型 方法名 (含有泛型的类名或者接口名<泛型> 对象名) {}
      
    • 上述格式简化如下:

      修饰符 返回值类型 方法名 (含有泛型的类名或者接口名<?> 对象名) {}
      

2.4.2 上限

  • 格式

    <? extends 泛型> 泛型的类型只允许泛型类型本身或者是该类型的子类类型

2.4.3 下限

  • 格式

    <? super 泛型> 泛型的类型只允许泛型类型本身或者是该类型的父类类型
import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo14 {
    public static void main(String[] args) {
//A是B的父类,B是C的父类
        Collection<String> str = new ArrayList<>();
        Collection<Object> obj = new ArrayList<>();
        Collection<A> a = new ArrayList<>();
        Collection<B> b = new ArrayList<>();
        Collection<C> c = new ArrayList<>();

        MyList myList = new MyList();

        myList.method(str);
        myList.method(obj);
        myList.method(a);
        myList.method(b);
        myList.method(c);

//        myList.show(str);
//        myList.show(obj);
//        myList.show(a);
        myList.show(b);
        myList.show(c);

//        myList.show1(str);
        myList.show1(obj);
        myList.show1(a);
        myList.show1(b);
//        myList.show1(c);
    }
}
import java.util.Collection;

public class MyList {
    public void method (Collection<?> coll) {
        System.out.println(coll.getClass());
    }
    public void show (Collection<? extends B> coll) {}

    public void show1 (Collection<? super B> coll) {}
}

3、List接口

  • 特点:
    • 有序的集合
    • 有索引的集合
    • 可以有重复元素
    • List接口的实现类们一共有四种形成索引的方式:数组结构、链表结构、(栈、队列)
  • 位置:java.util
  • 方法
  1. void add(int index,E element)

    在列表的指定位置插入指定元素(可选操作)。

  2. E get(int index)

    返回列表中指定位置的元素。

  3. int indexOf(Object o)

    返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。

  4. int lastIndexOf(Object o)

    返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。

  5. ListIterator listIterator()

    返回此列表元素的列表迭代器(按适当顺序)。

  6. E remove(int index)

    移除列表中指定位置的元素(可选操作)。

  7. E set(int index,E element)

    用指定元素替换列表中指定位置的元素(可选操作)。

  8. List subList(int fromIndex,int toIndex)

    返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

3.1 List集合的五种遍历方式

  • 迭代器
  • 增强for(JDK5.0)
  • Stream流(JDK8.0)
  • List特有迭代器:listIterator
  • 普通for
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.stream.Stream;

public class ListDemo01 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        ListIterator<String> stringListIterator = list.listIterator();
        while (stringListIterator.hasNext()){
            System.out.println(stringListIterator.next());
        }

        for (String s : list) {
            System.out.println(s);
        }

        Stream<String> stream = list.stream();
        stream.forEach(System.out::println);

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

3.2 List集合删除时的注意事项(remove方法)

  • 集合删除时的注意事项:

    集合的长度和索引在进行删除后都是变化的

  • 解决方案
    1. 每次删除成功,将索引进行-1
    2. 倒序删除
    3. 迭代器

补充:使用String类的equals()时,习惯使用字符串字面值常量进行调用,将变量传入方法中,这样可以避免空指针异常

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

public class ListDemo04 {
    public static void main(String[] args) {
        method2();
    }


    private static void method() {
        List<String> list = new ArrayList<>();

        list.add("100元");
        list.add("100元");
        list.add("100元");
        list.add("50元");
        list.add("10元");

        for (int i = 0; i < list.size(); i++) {
            if ("100元".equals(list.get(i))){
                list.remove(i);
                i--;
            }
        }
        System.out.println(list);
    }
    private static void method1() {
        List<String> list = new ArrayList<>();

        list.add("100元");
        list.add("100元");
        list.add("100元");
        list.add("50元");
        list.add("10元");

        for (int i = list.size() - 1; i >= 0; i--) {
            if ("100元".equals(list.get(i))){
                list.remove(i);
            }
        }
        System.out.println(list);
    }
    private static void method2() {
        List<String> list = new ArrayList<>();

        list.add("100元");
        list.add("100元");
        list.add("100元");
        list.add("50元");
        list.add("10元");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String str = iterator.next();
            if ("100元".equals(str)){
                iterator.remove();
            }
        }
        System.out.println(list);
    }
}

4、ArrayList集合类

  • 特点:

    1. ArrayList集合底层数据结构:数组结构

    2. 数组结构的特点:查询效率高,增删效率低

    3. ArrayList集合可以存储null元素,获取时需要针对所有元素进行非空校验,否则可能空指针异常

    4. 线程不安全,适用于单线程程序,执行效率高。如果在多线程中进行使用需要手动添加线程安全

    5. ArrayList集合底层数组的初始容量:取决于构造器

      (1)ArrayList()无参构造器:

      ​ JDK6.0(包含)以前:10

      ​ JDK7.0(包含)以后:0,在第一次添加元素时初始化为10

      (2)ArrayList(Collection<? extends E> c)

      ​ 参数长度

      ​ (3)ArrayList(int initialCapacity)

      ​ 自定义容量

    6. 扩容

      ​ JDK6.0(包含)以前:(原来数组长度*3)/2-1

      ​ JDK7.0(包含)以后:原来数组长度+原来数组长度 >> 1

5、Vector类

  • 特点:被ArrayList替代(JDK1.2),与ArrayList同。
  1. Vector集合底层数据结构:数组结构

  2. 数组结构的特点:查询效率高,增删效率低

  3. Vector集合可以存储null元素,获取时需要针对所有元素进行非空校验,否则可能空指针异常

  4. 线程安全,适用于多线程程序,执行效率低。

  5. Vector集合底层数组的初始容量和增量:取决于构造器

    (1)Vector()无参构造器:

    ​ 初始容量:10

    ​ 增量:0

    (2)Vector(Collection<? extends E> c)

    ​ 初始容量:参数长度

    ​ 增量:0

    ​ (3)ArrayList(int initialCapacity)

    ​ 初始容量:自定义容量

    ​ 增量:0

    ​ (4)ArrayList(int initialCapacity,int capacityincremental)

    ​ 初始容量:自定义容量

    ​ 增量:自定义容量

  6. 扩容

    ​ 原来数组长度+((增量 > 0) ?增量 :原来数组长度 )

  • 位置:java.util

6、LinkedList类

  • 特点

    List接口的(双向)链接列表实现。相比于数组,查询效率低,增删效率高

    线程不安全

    可以存储null

  • 方法:

  1. public void addFirst(E e)

    将指定元素插入此列表的开头。

  2. public void addLast(E e)

    将指定元素添加到此列表的结尾。

  3. public E getFirst()

    返回此列表的第一个元素。

  4. public E getLast()

    返回此列表的最后一个元素。

  5. public E removeFirst()

    移除并返回此列表的第一个元素。

  6. public E removeLast()

    移除并返回此列表的最后一个元素。

7、List小结

  • 如果操作的数据查询偏多,选择ArrayList集合;
  • 如果操作的数据增删偏多,选择LinkedList集合;
  • 如果涉及线程安全,选择Vector或者根据实际情况选择ArrayList和LinkedList并手动给其添加线程安全

Today Code

collection:

  1. 集合的概述
  2. Collection接口
  3. Collection集合的面试题
  4. Collection通用的遍历方式:迭代器
  5. 迭代器的注意事项
  6. 增强for
  7. 增强for的注意事项
  8. Stream流
  9. 泛型的概述
  10. 含有泛型的类
  11. 含有泛型的接口
  12. 含有泛型的方法
  13. 泛型的高级应用
  14. 泛型的受限

list:

  1. List接口
  2. List接口的方法
  3. List集合的五种遍历方式
  4. List集合删除时的注意事项(remove方法)
  5. ArrayList实现类
  6. Vector类
  7. LinkedList类
  8. List小结
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MelodyYN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值