Java笔记之集合(十九)

一、集合基本介绍

1.基本介绍

为什么引入集合

  1. 由于数组的长度开始时必须指定,而且一旦指定就不能更改
  2. 保存的元素必须是同一类型的元素
  3. 而且使用数组添加、删除元素比较麻烦

集合的特点

  1. 可以动态保存任意多个对象,使用比较方便
  2. 提供了一系列方便的操作对象的方法 如:add,get,set
  3. 使用集合添加、删除新元素代码简洁了很多

2.集合的框架体系图☆

java中的集合类很多,注意分为两大类,如图所示

Collection接口
在这里插入图片描述
Map接口

在这里插入图片描述

二、Collection 接口

Collection接口实现类的特点

  1. Collection实现子类可以存放多个元素,每个元素可以是Object
  2. 有些Collection的实现类,可以存放重复的元素,有些不可以
  3. 有些Collection的实现类,有些事有序的(List),有些不是有序(Set)
  4. Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的

1.Collection接口常用方法

import java.util.ArrayList;

class test1{
    @SuppressWarnings({"all"})  //去除警告
    public static void main(String[] args){
        //ArrayList是一个实现Collection接口的子类
        ArrayList list = new ArrayList();
        //添加元素
        list.add("jack");
        list.add(10);
        list.add(true);
        System.out.println("list="+list);   //list=[jack, 10, true]

        //删除元素
        list.remove(0); //删除第一个元素
        list.remove(true);  //删除指定元素

        //判断元素是否存在
        System.out.println(list.contains(10));  //true

        //获取集合元素个数
        System.out.println(list.size());    //1

        //判断集合是否为空
        System.out.println(list.isEmpty()); //false

        //清空集合
        list.clear();
        System.out.println(list);   //[]

        //addAll(Collection c)添加多个元素
        ArrayList list1 = new ArrayList();
        list1.add(1);
        list1.add(2);
        list.addAll(list1);
        System.out.println(list);   //[1,2]

        //查找多个元素是否存在
        list.add("test");   //再添加一个元素
        System.out.println(list.containsAll(list1));    //true

        //删除多个元素
        list.removeAll(list1);
        System.out.println(list);   //[test]
    }
}

2.Iterator(迭代器)

基本介绍

  1. Iterator对象称为迭代器,注意用于遍历Collection集合中的元素
  2. 所有实现了Collection接口的集合都有一个Iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器
  3. Iterator仅用于遍历集合

常用方法
在这里插入图片描述
注意:在调用iterator.next()方法之前必须要调用iterator.hasNext()进行检测。若不调用,且下一条记录无效,直接调用iterator.next()会抛出异常

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

class test1{
    @SuppressWarnings({"all"})
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        list.add(new Person("张三",18));
        list.add(new Person("李四",19));
        list.add(new Person("王五",20));

        System.out.println("第一次遍历");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);
        }

        System.out.println("第二次遍历");
        //注意:如果想第二次遍历,需要重置的迭代器
        iterator = list.iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }
}

class Person{
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //这个get和set省略了

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3.增强for循环

增强for循环,可以代替Iterator迭代器,特点:增强for就是简化版的Iterator本质一样,只能用于遍历集合或数组

基本语法
for(元素类型 元素名:集合名或数组名){
  访问元素
}

import java.util.ArrayList;

class test1{
    @SuppressWarnings({"all"})
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        list.add(new Person("张三",18));
        list.add(new Person("李四",19));
        list.add(new Person("王五",20));
        for (Object i: list) {
            System.out.println(i);
        }
    }
}

class Person{
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //这个get和set省略了

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

三、List 接口

基本介绍

  1. List集合类中元素有序(添加顺序和取出顺序一致)、且可重复
  2. List集合类中的每个元素都有其对应的顺序索引,即支持索引
  3. List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
  4. 常用的实现类有ArrayList、LinkedList和Vector

1.List集合类常用方法

这里以ArrayList()类为例,LinkedList()和Vector()类似
更多方法可查看API

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

class test1{
    @SuppressWarnings({"all"})
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        //add添加元素
        list.add("张三");
        list.add("张三");
        list.add("李四");

        //add(int index, Object element):在指定index位置添加元素
        list.add(1,"小明");   //索引从0开始的
        System.out.println(list);   //[张三, 小明, 张三, 李四]

        //add(int index, Collection c):在指定index位置将所有元素添加进来
        ArrayList list1 = new ArrayList();
        list1.add(1);
        list1.add(2);
        list.addAll(1,list1);
        System.out.println(list);   //[张三, 1, 2, 小明, 张三, 李四]

        //get(int index):获取指定index位置的元素
        System.out.println(list.get(0));    //张三

        //indexOf(Object obj):返回 obj 在集合中首次出现的位置
        System.out.println(list.indexOf("张三")); //0

        //lastIndexOf(Object obj):返回 obj 在当前集合中末次出现的位置
        System.out.println(list.lastIndexOf("张三")); //4

        //remove(int index):移除指定 index 位置的元素,并返回此元素
        list.remove(1);
        System.out.println(list);   //[张三, 2, 小明, 张三, 李四]

        //set(int index, Object ele):设置指定 index 位置的元素为 ele , 相当于是替换
        list.set(1,"tom");
        System.out.println(list);   //[张三, tom, 小明, 张三, 李四]

        //subList(int fromIndex, int toIndex):返回从 fromIndex 到 toIndex 位置的子集合
        List list2 = list.subList(1, 3);
        System.out.println(list2);  //[tom, 小明]
    }
}

2.List集合类的循环

  • 方式一:Iterator迭代器
  • 方式二:增强for循环
  • 方式三:使用普通for循环
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

class test1{
    @SuppressWarnings({"all"})
    public static void main(String[] args){
        //这三个类都是List接口的实现类
//        List list = new ArrayList();
        List linkedList = new LinkedList();
//        List vector = new Vector();

        linkedList.add(new Person("张三",21));
        linkedList.add(new Person("李四",19));
        linkedList.add(new Person("王五",20));

        //普通for遍历
        for (int i = 0; i < linkedList.size(); i++) {
            System.out.println(linkedList.get(i));
        }

        System.out.println("-------------------");

        sort(linkedList);

        //增强for循环
        for (Object o: linkedList) {
            System.out.println(o);
        }

        System.out.println("-------------------");

        //迭代器遍历
        Iterator iterator = linkedList.iterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);
        }
    }

    //年龄从小到大排序,冒泡排序
    public static void sort(List list){
        int listSize = list.size();
        for (int i = 0; i < listSize; i++) {
            for (int j = 0; j < listSize-1; j++) {
                Person o = (Person)list.get(j);
                Person o1 = (Person)list.get(j + 1);
                if (o.getAge()>o1.getAge()){
                    list.set(j,o1);
                    list.set(j+1,o);
                }
            }
        }
    }
}

class Person{
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }


    @Override
    public String toString() {
        return "姓名:"+name+"\t"+"年龄:"+age;
    }
}

四、ArrayList底层源码扩容机制

结论

  1. ArrayList中维护了一个Object类型的数组elementData
  2. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData的容量为0,第一次add添加,则扩容elementData为10,如果再需要扩容elementData的容量则为目前elementData容量的1.5倍
  3. 当创建ArrayList对象时,如果使用的是指定导向的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData的容量是目前elementData容量的1.5倍
import java.util.ArrayList;

class test1{
    @SuppressWarnings({"all"})
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
    }
}

下面是以上代码的Debug大致流程

(1)执行ArrayList list = new ArrayList();创建了一个elementData数组={ }
在这里插入图片描述
(2)执行list.add,首先把添加的值返回一个Integer类型的,完成装箱操作
在这里插入图片描述
(3)按照顺序依次执行
①调用ensureCapacityInternal(int minCapacity)方法,该方法首先调用calculateCapacity(elementData, minCapacity)
②判断elementData是否为空数组如果是空数组,就给一个最小容量DEFAULT_CAPACITY值为10
③然后再调用ensureExplicitCapacity方法再次确定一下是否扩容,然后判断一下最小的容量减去当前集合长度是否>0,如果>0,调用grow(minCapacity)方法进行扩容(也就是说我需要10个容量,当前集合的长度却是0)
在这里插入图片描述
(4)进入grow方法后,把集合的长度给oldCapacity,而newCapacity = oldCapacity+ oldCapacity/2(>> 1 表示位运算 向右移动一位),也就是1.5以前的1.5倍,如果newCapacity - minCapacity <0 ;则就把minCapacity 赋值newCapacity=10;

最后执行elementData = Arrays.copyOf(elementData, newCapacity);这条语句把newCapacity复制给elementData

在这里插入图片描述
(5)扩容完之后回到add方法中进行增加操作
在这里插入图片描述

五、Vector和LinkedList

1.Vector

基本介绍
在这里插入图片描述

  1. Vector底层也是一个对象数组,protected Object[] elementData;
  2. Vector是线程同步的,即线程安全
  3. Vector在开发中,如果需要线程同步安全时,则可以考虑使用Vector

Vector的常用方法跟ArrayList类似,具体查看JDK1.8

ArrayList 和 Vector 的比较

底层结构版本线程安全(同步)效率扩容倍数
ArrayList可变数组jdk1.2不安全,效率高如果无参 第一次容量为10,第二次开始按1.5扩容;如果有参按1.5扩容
Vector可变数组jdk1.0安全,效率不高如果无参 默认为10,满后,按2倍扩容;如果指定大小,则每次直接按2倍扩容

2.LinkedList

基本介绍
在这里插入图片描述

  1. LinkedList底层实现了双向链表和双端队列特点
  2. 可以添加任意元素(元素可以重复),包括null
  3. 线程不安全,不能实现同步

LinkedList的增删改查

import java.util.LinkedList;

class test1{
    @SuppressWarnings({"all"})
    public static void main(String[] args){
        //增
        LinkedList list = new LinkedList();
        list.add(1);
        list.add(2);
        System.out.println(list);   //[1, 2]

        LinkedList list1 = new LinkedList();
        list1.add("java");
        list1.add("python");
        list.addAll(list1);
        System.out.println(list);   //[1, 2, java, python]

        //删
//        list.remove();   //默认删除第一次元素
        list.remove(2);
        System.out.println(list);   //[1, 2, java, python]

        //改
        list.set(1,"scala");
        System.out.println(list);   //[1, scala, python]

        //获取
        System.out.println(list.get(1));    //scala
    }
}

ArrayList 和 LinkedList 的比较

底层结构增删效率改查的效率
ArrayList可变数组效率低,数组扩容较高
LinkedList双向链表较高,通过链表追加较低
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

王博1999

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

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

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

打赏作者

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

抵扣说明:

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

余额充值