Java集合类(Collection)详解及源码分析

Java集合类

两耳不闻窗外事,一心只读圣贤书。

1.概述

Java集合类主要是Collection接口下的单列集合和Map接口下的K-V键值对类型的集合。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HcTlpSSU-1644035373984)(F:\StudyNotepad\img\image-20211208170010452.png)]

2.Collection

2.1 Collection 中的常用方法

contains(Object o)

contains方法的作用是查询当前集合中是否存在所传入的值。

查询的方式是查询传入对象的hashcode。

举例:

Collection coll = new ArrayList();
// 对比测试实例化一个对象的hashCode
Person per1 = new Person("Tom");
Person per2 = new Person("Tom");
System.out.println(per1.hashCode());
System.out.println(per2.hashCode());
// 对比测试一个字符串对象的hashCode
String jack1 = new String("Jack");
String jack2 = new String("Jack");
System.out.println(jack1.hashCode());
System.out.println(jack2.hashCode());

coll.add(new Person("Tom"));
coll.add(new String("Jack"));
// 返回结果为false,hashCode不同。
System.out.println(coll.contains(new Person("Tom")));
// 这里返回的结果是True,说明contains方法查询的是hashCode值。
System.out.println(coll.contains(new String("Jack")));

结论:String类已经重写了equals方法,因此最后的hashCode是相同的。(重写的比较的是值来定义hashcode)

但是普通的类用的Object默认的equals,直接比较的内存地址,因此对于用户自定义的类,使用contains方法的结果是false。

本质是调用传入对象的equals方法来比较查询。

如果需要调用contains方法时,传入的对象需要重写equals方法。

containsAll(Collection coll)

传入的集合中的数据是否都存在需要查询的集合中。

注意:只有全部都在才会返回true。

remove(Object o)

通过equals来进行判断是否存在元素,如果存在就进行删除,删除成功返回true。

删除失败返回false。

removeAll(Collection coll)

从当前集合中移除传入的集合中的元素。

移除的是两个集合的交集。

retainAll(Collection coll)

获取两个集合的交集,并修改当前的集合。

使当前集合中只存在两个集合共同存在的。

equals(Object o)

比较两个集合是否相同。

注意:ArrayList是有序的,因此比较时顺序会影响结果,如果顺序不同也会返回false。

hashCode()

返回hashCode值,如果没有重写就是返回内存地址。

如果重写了hashCode方法,则返回的结果自定义。

toArray()

返回相应类型的数组。

如果没有使用泛型,那么默认是Object[]型数组。

补充:如果将数组转换为集合?

通过Arrays.asList([对象数组]),来进行数组到集合的转换。

注意:

​ 如果传入的是基本数据类型的数组(int、boolean等),那么会将传入的整个数组当成一个对象进行处理,只有转换为相应的包装类对象才能达到想要的结果。

List<int[]> ints = Arrays.asList(new int[]{
   1, 2, 3});
// 虽然我们上面定义的数组含有多个元素,但是因为是基本数据类型,list中需要存放的是
// 对象数据类型,那么就会将整个数组当成一个对象进行处理,最后输出的结果:长度为1。
System.out.println(ints.size());
// 解决办法:将基本数据类型的数组转换为包装类对象进行传入 ==》 new Integer[]
// 通过包装类对象以后就能正常将传入的数组转换为list
List<Integer> integers = Arrays.asList(new Integer[]{
   1, 2, 3});
System.out.println(integers.size());
iterator()

返回一个迭代器实例。

每次调用方法都会返回新的一个迭代器实例对象。

迭代器实例就是用于帮助我们遍历集合。

在Java设计模式中有详细的介绍。

注意:

​ Map中不是通过迭代器进行遍历,迭代器遍历主要引用与Collection中的集合。

  • hasNext()

    判断是否含有写一个

  • next()

    先指针下移,然后再输出元素

  • remove()

    移除当前遍历到的元素,先next以后才能remove,如果没有next直接remove那么会爆出:IllegalStateException

    原因:next开始是-1,那么无法删除,还有一种情况也会爆出这个异常,next以后进行了两次remove。

    同理,remove是删除当前元素,删除以后指针并没有发生改变,如果在remove就会爆出异常。

集合的遍历除了迭代器以外,还有一种是forEach,这也是比较常用的一种方式。

语法:for([Object类型] [集合中具体的元素]:[集合]){}

本身也是通过迭代器实现。

不能通过修改遍历出的值,来修改集合对象中的值。

原因:

​ 本身foreach是通过将集合中的值取出然后赋值到一个对象上,那么如果我们通过foreach来修改遍历出的值,是对本身集合对象是没有任何影响的。

forEach(Consumer action)

Collection类中默认是可以通过这个方法进行forEach遍历循环。

coll.forEach(System.out ::println);	

2.2 List

Collection中的一个子类接口。

存储有序的、可重复的数据。

2.2.1 概述
  • ArrayList
  • LinkedList
  • Vector
2.2.2 ArrayList、LinkedList、Vector的异同
相同点
  • 三个类都实现了List接口
  • 存储的数据都是有序、可重复的
不同点
  • ArrayList是作为List主要实现类(首选)

    线程不安全,效率高

    底层是通过Objec[]数组存储,动态扩展

  • Vector是List接口的古老实现类

    推出Java就已经存在的一个类(V 1.0)出现,List(V 1.2)才出现。

    线程安全,效率低

    底层是通过Objec[]数组存储,动态扩展

  • LinkedList通过链表实现和另外两种不同实现方式不同

    双向链表实现

    线程不安全

    对于增加/删除效率比数组实现的List类效率更高,同理查找没有数组实现的List类高

2.3 List中的实现类源码分析

2.3.1 ArrayList

构造方法,无参构造默认大小为10,但是不会再实例化对象时创建数组,而是创建一个空数组,当进行第一次执行add()方法时才会进行创建。

扩容为1.5倍加1。

  • Object[] elementData实现,动态扩容

    transient Object[] elementData; 
    
  • new实例对象时,可以指定大小,如果没有指定,那么默认创建大小为10

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
         
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
常用方法

下面演示add()方法。

其他方法类似在进行操作之前都会进行一些数组上面的判断。

add()

先判断,再添加。数组长度不够,扩容,每次扩容原先数组的1.5倍。

不是无止境的扩容,最大值为int类型最大值。

结论:建议在创建ArrayList时指定大小。

源码

public boolean add(E e) {
   
    // 添加元素前会进行容量判断如果容量够进行添加
    // 如果不够会进行扩容
    ensureCapacityInternal(size + 1);
    elementData[size++] = e;
    return true;
}
// 扩容判断
private void ensureExplicitCapacity(int minCapacity) {
   
    modCount++;
    // 判断当加入这个元素以后是否会超过数组的长度
    if (minCapacity - elementData.length > 0)
        // 如果加入元素超过了数组的长度,进行扩容
        grow(minCapacity);
}
// 进行扩容
private void grow(int minCapacity) {
   
    int oldCapacity = element
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java集合类的`sort()`方法可以对集合的元素进行排序。使用该方法需要注意以下几点: 1. 集合的元素必须实现`Comparable`接口或者你需要传递一个`Comparator`对象给`sort()`方法来指定排序方式。 2. 如果集合的元素没有实现`Comparable`接口,也没有传递`Comparator`对象,那么会抛出`ClassCastException`异常。 3. `sort()`方法会直接修改原来的集合,而不是返回一个新的排序后的集合。 下面是一个示例代码: ```java import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class SortExample { public static void main(String[] args) { // 创建一个List对象 List<String> list = new ArrayList<>(); list.add("apple"); list.add("banana"); list.add("orange"); // 对集合的元素进行排序 Collections.sort(list); // 输出排序后的结果 System.out.println(list); // 创建一个Comparator对象 Comparator<String> comp = new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }; // 使用Comparator对象对集合的元素进行排序 Collections.sort(list, comp); // 输出排序后的结果 System.out.println(list); } } ``` 该代码首先创建了一个`List`对象,并向其添加了三个元素。接着调用`Collections.sort(list)`方法对集合的元素进行了默认的升序排序,并输出排序后的结果。然后创建了一个`Comparator`对象来指定降序排序方式,再次调用`Collections.sort(list, comp)`方法对集合的元素进行排序,并输出排序后的结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值