19 集合

lix_uan
• 阅读 950

集合框架

集合和数组的区别

  • 数组的长度是固定的,集合的长度是可变的
  • 数组中存储的是同一类型的元素,可以存储基本数据类型的值;集合存储的都是对象,而且对象的类型可以不一致

Collection集合体系

19 集合

Map集合体系

19 集合

Collection常用功能

添加元素

  • add(E obj)
  • addAll(Collection<? extends E> other)

删除元素

  • boolean remove(Object obj)
  • boolean removeAll(Collection<?> coll)

判断元素

  • boolean isEmpty()
  • boolean contains(Object obj)

查询

  • int size()
  • Object[] toArray()

Iterator迭代器

public class IteratorDemo {
      public static void main(String[] args) {
        // 使用多态方式 创建对象
        Collection<String> coll = new ArrayList<String>();

        // 添加元素到集合
        coll.add("串串星人");
        coll.add("吐槽星人");
        coll.add("汪星人");
        //遍历
        //使用迭代器 遍历   每个集合对象都有自己的迭代器
        Iterator<String> it = coll.iterator();
        //  泛型指的是 迭代出 元素的数据类型
        while(it.hasNext()){ //判断是否有迭代元素
            String s = it.next();//获取迭代出的元素
            System.out.println(s);
        }
      }
}

使用Iterator迭代器删除元素

  • 既然Collection已经有remove(xx)方法了,为什么Iterator迭代器还要提供删除方法呢?

    • 因为Collection的remove方法,无法根据条件删除

          @Test
          public void test02(){
              Collection<String> coll = new ArrayList<>();
              coll.add("陈琦");
              coll.add("李晨");
              coll.add("邓超");
              coll.add("黄晓明");
      
              //删除名字有三个字的
              //coll.remove(o)//无法编写
      
              Iterator<String> iterator = coll.iterator();
              while(iterator.hasNext()){
                  String element = iterator.next();
                  if(element.length()==3){
                  //coll.remove(element);//错误的
                      iterator.remove();
                  }
              }
              System.out.println(coll);
          }

增强for

  • JDK1.5以后出来的一个高级循环,专门用来遍历数组和集合

  • 只能用来遍历元素,不能再遍历过程中进行增删操作

    public class NBForDemo1 {
        public static void main(String[] args) {
            int[] arr = {3,5,6,87};
               //使用增强for遍历数组
            for(int a : arr){//a代表数组中的每个元素
                System.out.println(a);
            }
        }
    }
    public class NBFor {
        public static void main(String[] args) {        
            Collection<String> coll = new ArrayList<String>();
            coll.add("小河神");
            coll.add("老河神");
            coll.add("神婆");
            //使用增强for遍历
            for(String s :coll){//接收变量s代表 代表被遍历到的集合元素
                System.out.println(s);
            }
        }
    }

快速失败机制

  • 使用foreach或Iterator遍历集合时,如果集合发生了修改,就会抛 ConcurrentModificationException异常

快速机制的实现

  • 在ArrayList等集合类中都有一个modCount变量。它用来记录集合的结构被修改的次数。
  • 当我们给集合添加和删除操作时,会导致modCount++。
  • 然后当我们用Iterator迭代器遍历集合时,创建集合迭代器的对象时,用一个变量记录当前集合的modCount。例如:int expectedModCount = modCount;,并且在迭代器每次next()迭代元素时,都要检查 expectedModCount != modCount,如果不相等了,那么说明你调用了Iterator迭代器以外的Collection的add,remove等方法,修改了集合的结构,使得modCount++,值变了,就会抛出ConcurrentModificationException

List集合

List接口的特点

  • 元素有序,可以重复

List接口中常用方法

  • 添加元素
    • void add(int index, E ele)
  • 获取元素
    • E get(int index)
    • List subList(int fromIndex, int toIndex)
  • 获取元素索引
    • int indexOf(Object obj)
    • int lastIndexOf(Object obj)
  • 删除和替换元素
    • E remove(int index)
    • E set(int index, E ele)

List的实现类

ArrayList集合

  • 数组结构,元素增删慢,查找快
  • 日常开发中多用来查询数据、遍历数据
  • 线程不安全

LinkedList集合

  • 链表结构,方便元素添加、删除
  • 双向列表

ListIterator

  • 继承了Iterator接口,提供了专门操作List的方法

        public static void main(String[] args) {
            List<Student> c = new ArrayList<>();
            c.add(new Student(1,"张三"));
            c.add(new Student(2,"李四"));
            c.add(new Student(3,"王五"));
            c.add(new Student(4,"赵六"));
            c.add(new Student(5,"钱七"));
    
            //从指定位置往前遍历
            ListIterator<Student> listIterator = c.listIterator(c.size());
            while(listIterator.hasPrevious()){
                Student previous = listIterator.previous();
                System.out.println(previous);
            }
        }

ArrayList源码分析

JDK1.8

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//初始化为空数组
    }
    public boolean add(E e) {
        //查看当前数组是否够多存一个元素
        ensureCapacityInternal(size + 1);  // Increments modCount!!

        //存入新元素到[size]位置,然后size自增1
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        //如果当前数组还是空数组
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //那么minCapacity取DEFAULT_CAPACITY与minCapacity的最大值
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //查看是否需要扩容
        ensureExplicitCapacity(minCapacity);
    }
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//修改次数加1

        // 如果需要的最小容量  比  当前数组的长度  大,即当前数组不够存,就扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//当前数组容量
        int newCapacity = oldCapacity + (oldCapacity >> 1);//新数组容量是旧数组容量的1.5倍
        //看旧数组的1.5倍是否够
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //看旧数组的1.5倍是否超过最大数组限制
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);

        //复制一个新数组
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

Set集合

  • set集合不允许包含相同元素
  • 支持使用foreach和Iterator遍历

HashSet

  • 底层是HashMap

TreeSet

  • 底层是TreeMap,基于红黑树实现

  • 把一个对象添加到TreeSet时,该对象的类必须实现Comparable接口

  • 对于TreeSet而言,判断两个对象相等的唯一标准是:两个对象通过compareTo方法比较返回值是0

    @Test
    public void test1(){
        TreeSet<String> set = new TreeSet<>();
        set.add("zhangsan");  //String它实现了java.lang.Comparable接口
        set.add("lisi");
        set.add("wangwu");
        set.add("zhangsan");
    
        System.out.println("元素个数:" + set.size());
        for (String str : set) {
            System.out.println(str);
        }
    }
  • 如果没有实现Comparable接口,则要单独指定Comparator比较器

    @Test
    public void test3(){
        TreeSet<Student> set = new TreeSet(new Comparator<Student>(){
    
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getId() - o2.getId();
            }
    
        });
        set.add(new Student(3,"张三"));
        set.add(new Student(1,"李四"));
        set.add(new Student(2,"王五"));
        set.add(new Student(3,"张三风"));
    
        System.out.println("元素个数:" + set.size());
        for (Student stu : set) {
            System.out.println(stu);
        }
    }
点赞
收藏
评论区
推荐文章

暂无数据

lix_uan
lix_uan
Lv1
学无止境,即刻前行
文章
7
粉丝
5
获赞
0