Java集合框架

本文详细介绍了Java集合框架,包括集合、数组的区别,Collection接口及其常用方法,List接口的实现类如ArrayList、LinkedList、Vector、Stack的特点和原理,Queue接口与Deque接口,泛型的概念、分类和通配符,以及Set接口的实现类HashSet和TreeSet的存储原理。此外,还讨论了Map接口的HashMap、TreeMap、LinkedHashMap和HashTable的区别与实现机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java集合框架概述

集合可以看作是一种容器,用来存储对象信息。所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurrent包下。

一: 集合框架特点介绍

1.集合的概念

JavaAPI所提供的一系列类的实例,可以用来动态的存放多个对象。

Java集合框架提供了一套性能优良,使用方便的接口和类,位于java.util包中。

集合的特点:

  • 长度不固定,只能存储引用类型的对象。

  • 特点:代表一组任意类型的对象,无序,无下标,不能重复

2.集合与数组的区别

集合

数组

长度

长度可变

长度不可变

存储内容

可以存储不同类型的数据

只能存储同一类型的数据

数据类型

只能存储引用数据类型

可以存储基本数据类型和引用数据类型

3.集合框架图

二: collection接口

1.collection特点:

  1. 部分集合实现是有序的,部分集合实现是无序的(set)。这里的有序指的(List)是存储的顺序

  1. 部分集合实现是可排序的(SortedSet),部分集合实现是不可排序的

  1. 部分集合是可重复的(List),部分是**不可重复(Set)**的

1.1.collection常用方法:
 //多态 new一个接口的实现类给这个引用
        //ArrayList 实现了List接口类,而List继承了Collection父类  
        // 多态的思想 一个对象的实际类型是确定的,但可以指向对象的引用的类型(父类或有关系的类)
Collection collection = new ArrayList();
//添加
collection.add("小明");
collection.add("小红");
collection.add(1);//这里的1是由基本数据类型自动装箱转换成了包装类
collection.add(true);
//删除
collection.remove("小明");
//collection.removeAll(collection);//删除全部

//修改 在Collection接口中没有提供直接修改的方法,如果要修改那么可以先删除在新增
collection.remove("小红");
collection.add("小李");

//循环遍历功能
Object[] objects = collection.toArray();
for (Object object : objects) {
    System.out.println(object);
}

//判断功能
System.out.println(collection.contains("小李"));//true
System.out.println(collection.contains("小李子"));//false
System.out.println(collection.isEmpty()); //判断是否为空

//其他功能
System.out.println(collection.size());//获取集合元素个数

2.iterator接口

集合上的迭代器。实现了collection接口的集合类都有一个iterator(),该方法返回一个iterator接口对象,用来遍历对集合中的数据进行遍历

boolean hasNext() 
//返回 true如果迭代具有更多的元素。  
E next() 
//返回迭代中的下一个元素。  
default void remove() 
//从基础集合中移除这个迭代器返回的最后一个元素(可选操作)。  
2.1.hasNext()方法
 Collection cl = new ArrayList<>();
cl.add("张三1");
cl.add("张三2");
cl.add("张三3");
cl.add("张三4");
Iterator iterator = cl.iterator();
//hasNext 判断索引(游标)右边是否有元素
//next(),返回索引右边的的元素,并将索引移动到下一个位置
while (iterator.hasNext()){//判断是否有下一个元素
    //条件成立 获取下一个元素并移动游标位置
    System.out.print(iterator.next());
    //张三1张三2张三3张三4
}
2.2.remove方法
public static void main(String[] args) {
    Collection cl = new ArrayList<>();
    cl.add("张三1");
    cl.add("张三2");
    cl.add("张三3");
    cl.add("张三4");
    Iterator iterator = cl.iterator();

    while (iterator.hasNext()){//判断是否有下一个元素
        //条件成立 获取下一个元素并移动游标位置
        iterator.next();
        iterator.remove();//移除游标左侧的元素 必须先移动下标在执行删除
    }
    System.out.println(cl);
}

3.foreach循环

在collection集合中我们可以使用foreach循环来实现遍历集合中的元素

Collection cl = new ArrayList<>();
cl.add("张三1");
cl.add("张三2");
cl.add("张三3");
cl.add("张三4");
Iterator iterator = cl.iterator();

for (Object o:cl){
    System.out.println(o);
}

三: list接口

1.List概念介绍

List集合代表一个有序、可重复集合,集合中每个元素都有其对应的顺序索引。List集合默认按照元素的添加顺序设置元素的索引,可以通过索引(类似数组的下标)来访问指定位置的集合元素。

List接口是Collection接口子接口

实现List接口的集合主要有:ArrayListLinkedList、Vector、Stack。

2.List常用方法

2.1常用增删改查方法
List list = new ArrayList();
//添加  可添加重复的和null数据
list.add(1);
list.add(1);
list.add(null);

//list接口新增的方法 add(int index, E element) addAll(int index, Collection<? extends E> c)
//添加指定位置元素 超出list两个元素 会报错
//list.add(4, 1);//IndexOutOfBoundsException
list.add(3, 1);
System.out.println(list);

//list根据下标删除方法 删除
list.remove(1);

//list根据下标修改方法
list.set(0, 2);

//通过获取下标值遍历list
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}
2.2其他方法

根据值获取所在的索引值

List list = new ArrayList();

list.add(1);
list.add(2);
list.add("张三");
list.add("李四");
list.add("王五");
list.add(1);

//indexOf 根据值获取第一个出现的索引值 未找到返回-1
System.out.println(list.indexOf(1));
//lastIndexOf 根据值获取最后一次出现的索引值 未找到返回-1
System.out.println(list.lastIndexOf(1));
//subList获取指定索引区间的值 超出索引值报IndexOutOfBoundsException异常
System.out.println(list.subList(1,8));

3.ListIterator接口

ListIterator在util包下继承了Iterator类拥有Iterator类公共方法

在Iterator正向迭代的基础上拓展了逆向迭代

List list = new ArrayList();
list.add(1);
list.add(2);
list.add("张三");
list.add("李四");

//获取ListIterator接口实例
ListIterator iterator = list.listIterator();

//正向迭代判断是否有下一个元素
while (iterator.hasNext()){
   //nextIndex:获取游标下一个元素的索引值    next:返回游标右边的值,并将右边移动到下一位
    System.out.print(iterator.nextIndex()+":"+iterator.next());
    //0:1 1:2 2:张三 3:李四
}

//逆向迭代,判断上一位是否有元素
while (iterator.hasPrevious()){
    //previousIndex:获取游标左边元素索引 previous:返回左边索引值,并向左移动
    System.out.print(iterator.previousIndex()+":"+iterator.previous());
    //3:李四 2:张三 1:2 0:1
}

4.List接口的相关实现类

4.1ArrayList

ArrayList是一个动态数组,也是我们最常用的集合,是List类的典型实现。它允许任何符合规则的元素插入甚至包括null。每一个ArrayList都有一个初始容量(10),该容量代表了数组的大小。随着容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。所以如果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。

ArrayList擅长于随机访问。同时ArrayList是非同步的 。

4.1.1 ArrayList特点
  1. 底层的数据结构是数组

  1. 能够存储null值

  1. 线程不安全,但是效率高

  1. 底层是数组结构,那么查询和修改的效率高,增加和删除的效率就低了

  1. 有索引,能够方便的检索

  1. 元素是可以重复的,我们可自己去重

  1. 不可以排序

注意:Arraylist中常用的方法都来自于父类Collection、List、Object。
4.1.2 ArrayList原理分析
1.默认属性
/**
*集合默认容量
*/
private static final int DEFAULT_CAPACITY = 10;

/**
 * 空数组
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
 * 默认容量为空的数组
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
 * 集合中真实存储数据的数组
 */
transient Object[] elementData; // non-private to simplify nested class access

/**
 * 集合中元素的的个数,注意 不是数组的长度
 */
private int size;
2.构造方法
  • 无参构造:创建了一个空的数组

ArrayList list = new ArrayList();

/**ArrayList()源码
 * 构造一个初始容量为10的空列表
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
  • 有参构造:创建了一个指定容量的数组

ArrayList list = new ArrayList(20);

/**ArrayList(20)源码
   1.构造具有指定初始容量的空列表
   2.如果指定初始容量是负的,则抛出IllegalArgumentException异常
*/
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}
3.add()方法
ArrayList list = new ArrayList();
    list.add(10);
/**add源码
 *将指定的元素附加到此列表的末尾。
 */
public boolean add(E e) {
    //确认内部容量
    ensureCapacityInternal(size + 1);  
    //将要添加的元素放在数组的下一个
    elementData[size++] = e;
    return true;
}

第一步.ensureCapacityInternal确保内部容量 方法源码

private void ensureCapacityInternal(int minCapacity) {
    //{}                       {}
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //1                          10               1
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
	//明确数组的容量
    ensureExplicitCapacity(minCapacity);
}

第二步.ensureExplicitCapacity明确数组的容量 方法源码

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;//记录我对当前集合操作的次数

    // 10-0 > 0
    if (minCapacity - elementData.length > 0)
        //进行扩容
        grow(minCapacity);
}

第三步.grow扩容方法源码

/**
 * 增加容量以确保它至少可以容纳由最小容量参数指定的元素数量。
 */
private void grow(int minCapacity) {
    // 原来的容量 0
    int oldCapacity = elementData.length;
    //新的容量 0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //新容量 0 - 最小容量10 < 0
    if (newCapacity - minCapacity < 0)
        //新容量 = 10
        newCapacity = minCapacity;
    //新容量 10 - 数组最大值 21亿 > 0
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        //将把Intger容量大小(2的31立方)付给它
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值