java集合简单学习笔记

好处:
(1)集合可以动态保存任意多个对象,使用比较方便
(2)集合提供了多种方法,增删改查都可以直接调用方法,程序员更加关注业务逻辑 ,而不是底层代码
(3)使用集合添加删除元素的代码比较简洁
单列集合和双列集合
Collection接口下有两个重要的接口 Set和List 这属于单列集合
Map接口的实现子类这些都属于双列集合,键值对一起存放

几个重要集合的实现继承关系图
在这里插入图片描述
在这里插入图片描述
遍历方法一
Iterator 接口遍历(迭代器) 快捷键 itit
(每个Collection的实现子类都由自己对应的迭代器,作用:遍历集合)
hasNext():判断结合下一个元素是不是存在
next():向下移,同时返回下移后指向的元素,返回的元素的类型是Object
remove()
调用iterator.next()之前必须先用iterator.hasNext()方法检测。否则会抛出一个空元素异常
使用迭代器遍历一次后,如果想再次遍历集合,需要将迭代器重置。
ps: 取出迭代器后立即进行遍历,如果中间再次修改集合元素,可能就会抛出java.util.ConcurrentModificationException异常

遍历方法二
使用增强for循环,这种循环方式也可以用在数组上
增强for底层也是由迭代器实现的,可以认为是简化版的迭代器
快捷键 :I

** List**
(1)元素添加和取出顺序一致,并且可以重复
(2)每个元素都有对应的顺序元素索引,支持索引访问
实现子类听多的,常用的是Vector,ArrayList,LinkedList
遍历方式有三种,除了上面两种以外,还有普通for循环也可以

ArrayList
底层源码分析,ArrayList中维护了一个Object类型的数组elementData,当创建ArrayList对象时,如果使用无参构造器,则数组容量为0,初次添加元素的时候数组扩容为10,之后每次扩容时数组都扩容为原来的1.5倍,如果使用的是指定大小的构造器,则初始的数组为指定大小

B站韩顺平学Java视频截图
在这里插入图片描述
Vector
底层也是一个对象数组,Vector是线程同步的,即线程安全的,操作方法带有synchronized关键字
,线程同步安全时推荐使用Vector,效率比ArrayList低
无参构造时默认大小为10,每次扩容是原来的两倍,满了之后每次两倍扩容

LinkedList
双向链表和双端队列
底层维护了一个双向链表,维护了两个属性分别指向链表的首尾节点,每个节点里面又维护了prev,next和item三个属性,分别指向前一个和后一个节点,因此,添加和删除元素效率较高,remove方法默认删除第一个元素

如果改查操作多,可以偏向使用ArrayList.如果是增删操作多,可以偏向使用LinkedList,根据业务模块灵活选择

Set接口基本介绍
(1)无序,添加取出的顺序不一致,也没有索引
(2)没有重复的元素,最多一个null
(3)实现类比较多,常用的是HashSet和TreeSet
(4)取出的顺序虽然不是添加的顺序,但是是固定的(不会一直变)
可以使用增强for循环和迭代器两种遍历方式

HashSet
实现了Set接口,底层实际是HashMap,不能存放重复的元素,不保证元素的存取顺序一致
HashSet的底层是HashMap,而HashMap的底层是链表+数组+红黑树
(hash() + equals())
第一次数组扩容为16,之后每次元素个数(指的不是数组的索引个数,指的是所有链表里的所有的节点个数)超过阈值(数组长度的0.75)则数组长度会扩容为原来数组的二倍,链表长度超过一定长度(默认为8)时可能会树化(数组长度不到64会对数组进行扩容,数组长度超过64后会树化)。

LinkedHashSet
是HashSet的一个子类,底层是LinkedHashMap(HashMap的子类),底层维护了一个数组加双向链表,根据元素的HashCode值来决定元素的存储位置,同时以链表来维护元素的次序,使得元素看起来是以插入顺序保存的,不允许添加重复元素
在这里插入图片描述

Map接口
保存具有映射关系的数据 Key-Value
Map中的Key和Value可以是任何引用类型的数据(常用String作为Key),会封装到HashMap$Node对象中
Map中的Key不允许重复,原因同HashSet,
相同Key不同Value存入,采用替换Value机制(键唯一),Value可以重复
相同Value,不同Key,会直接新建
Key和Value存在单向一对一的关系
在这里插入图片描述
Map接口的遍历方法
1.将key取出,然后遍历(1)增强for(2)迭代器
2.将value取出,然后遍历 (1)增强for(2)迭代器 (只能看到值,无法看到键)
3.使用EntrySet取出 键值对,中间有一步Object向下转型为Map.Entry(转为这种类型的原因是可以使用getKey()和getValue()方法

 //3.使用EntrySet获取k-v
        //(1)增强for
        Set entryset = map.entrySet();
        for (Object entry :entryset) {
            //entry此时的编译类型是Object,运行类型是HashMap$Node,但是HashMap$Node不能使用两个取值方法
            Map.Entry m = (Map.Entry)entry;//将Object类型的entry向下转型为Map.Entry类型的m,就可以使用两个方法了
            System.out.println(m.getKey()+"-"+m.getValue());
        }
        //(2)迭代器
        Iterator iterator2 = entryset.iterator();
        while (iterator2.hasNext()) {
            Object next =  iterator2.next();
            Map.Entry m2 = (Map.Entry)next;
            System.out.println(m2.getKey()+"--"+m2.getValue());
        }

Map接口的常用实现类有 HashMap,Hashtable,Properties

HashMap
底层是以Hash表的形式存储的,与HashSet一样不保证映射的顺序
键和值都可以为空,但是不能重复
没有实现同步,因此线程不安全,方法没有做同步互斥的操作,没有synchronized
HashMap的扩容机制和HashSet扩容机制完全一样,因为HashSet底层就是HashMap

b站韩顺平视频截图
在这里插入图片描述
Hashtable
继承了Dictionary,实现了Map接口
键和值都不能为null,否则抛出空指针异常
使用方法与HashMap基本一样,Hashtableh是线程安全的,而HashMap是线程不安全的
底层有数组 Hashtable$Entry[] 初始化大小是11(Entry是Hashtable的内部类),扩容因子是0.75,每次扩容为原来的2倍+1
在这里插入图片描述
在这里插入图片描述
Properties
Properties是Hashtable的子类,并且实现了Map接口,xxx.proprtties通常作为配置文件,也不能存null,

韩顺平老师总结的选择集合类的思路
在这里插入图片描述
TreeSet
构造对象时,可以传入比较器(匿名内部类)指定排序,看源码发现原来构造器把传入的比较类对象,赋给了底层的TreeMap的属性this.comparator,之后运行add方法的时候,比较的时候,会动态绑定到匿名内部类(对象)compare方法,会调用传入时指定的规则进行比较,传入的比较器不为空时,底层会有一个do while循环循环比较传入的值和已有的值(使用指定的规则),之后会根据规则进行相应的添加操作(或者不添加,内容一样就不会添加,内容是否一样由程序员指定)
在这里插入图片描述
TreeMap
实现了Map接口,详细规则参考TreeSet理解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值