详讲Java集合类 (数组和集合的区别)

 数组和集合的区别:

数组: 存储多个数据
     相同数据类型的有序集合
    特点:
        1.引用数据类型,对象数据
        2.定长的,长度一旦确定不可改变
        3.有序的,从0开始,每次+1
        4.数据类型要求相同

 集合:
    存储任意类型的数据(引用数据类型)
    根据数据的增删长度自动改变

在这里插入图片描述

 Collection接口


构成Collection的单位是元素。Collection接口通常不能直接使用,但是该接口提供了添加元素,删除元素,管理数据的方法。由于List接口与Set接口都继承了Collection接口,因此这些方法对List集合和Set集合是通用的。

List集合


List集合包括List接口以及List接口的所以实现类。List接口的所有实现类。

List集合的特点:

List集合中的元素允许重复(可重复),各元素就是对象插入的顺序(有序),类似Java可以通过索引来访问集合中的元素(有索引)。

List接口继承了Collection接口,因此包含Collection中的所有方法,此外,List接口还定义了两个重要的方法。
get()方法和set()方法。

List接口的实现类:主要常用的是:ArrayList,LinkedList,Vector。

遍历方式: 1)for  2)foreach  3)iterator   4)listIterator

ArrayList : 有序(添加的顺序与内部存储数据的顺序一致),有索引  可重复
    List接口的可调整大小的阵列实现。 实现所有可选列表操作,并允许所有元素,包括null 。
    底层结构: 数组|可变数组
    特点: 查询效率高    增删效率低
    应用场景: 适合应用在大量查询,少量增删的位置
    扩容机制: 初始容量默认为10 DEFAULT_CAPACITY = 10,每次扩容原容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    新增功能: 无新增方法
 

Vector : 向量
    与ArrayList类似
    1) 扩容  : Vector每次扩容原容量的2倍 ,ArrayList 每次扩容原容量的1.5倍
    2) 同步问题 : Vector线程安全的|同步的, ArrayList线程不安全|不同步

LinkedList : 有序  可重复
    双链表,并允许所有元素(包括null )。
    底层结构: 双向链表结构
        数据以节点为单位,记录上下节点的地址
    特点: 查询效率较低,增删效率高
    应用场景: 大量做增删,少量做查询的地方
    新增功能: 根据链表头尾进行操作的方法

注意:

定义List存储自定义引用数据类型数据的时候,javabean中应该重写equals与toString

javabean规范:

1)类是公共的

2)至少提供一个空构造

3)属性私有化

4)公共的访问方式

5)重写toString与equals

6)根据需要实现序列化接口

Set集合

特点:无序(添加的顺序与内部真实存储数据的顺序不一致),不可重复,没有索引 

Set接口的实现类:主要常用的是:TreeSet,HashSet。 

遍历方式: 1) foreach   2)iterator

TreeSet : 无序,不可重复
    底层结构: 红黑树(平衡二叉树)
    特点: 数据默认升序排序
    应用场景: 存储多个数据中不允许重复数据,并且想要排序就可以选中使用TreeSet
    新增方法: 新增了一些与比较相关的方法

注意: 不同类型的数据不能使用TreeSet实现排序
自定义引用数据类型如何实现默认升序排序?
    定义User类型,存储多个用户对象放入TreeSet集合,是否能够成功实现排序,是否能够实现去重
    自定义引用数据类型对象存储: 要求定义比较规则
    自定义引用数据类型的去重: 根据比较规则的返回值做去重,返回值为0代表相同,去重
    自定义引用数据类型的排序: 根据比较规则的做排序,默认升序排序,可以根据比较规则方法的实现,实现一个降序排序

比较规则:
    内部比较器|自然排序 : 比较规则定义在类的内部
        自定义引用数据类型实现Comparable<T>接口,重写compareTo方法,方法的内部制定当前类型数据的比较规则
        根据compareTo返回值决定去重与排序
            o1.compareTo(o2)
                0  --> o1=o2
                负数 --> o1<o2
                正数 --> o1>o2

    外部比较器|定制排序 : 比较规则定义在类的外部(一般使用匿名内部类实现外部比较器)
        定义一个实现类,实现Comparator接口,重写compare方法,在方法内部制定比较规则

    总结:
        定义TreeSet集合的时候,构造器的参数是否指定使用哪一种外部比较规则,如果没有指定外部比较规则,默认找到数据的内部比较规则
            如果外部与内部比较规则都不存在,排除类型转换异常
       匿名内部类用来简化没有自己作用的,使用次数比较少的,接口实现类

HashSet : 无序  不可重复
    底层: 是由HashMap维护的
    底层: 哈希表(数组+链表+红黑树)

    特点: 查询,增删效率高
          无序,去重
    新增功能: 无新增方法
   

    自定义引用数据类型数据的去重: 两个对象所有成员变量的值都想等,应该去重
        javabean类中重写hashCode与equals方法,实现根据所有成员变量的值进行计算,而非默认的地址

    hashCode与equals之间的关系:
        两个对象,调用hashCode相等,equals就一定相等???  --> 不对
               hashCode相等,证明数据存储在同一个位桶中,但是equals不一定相等,所有多个数据之间才使用链存储
        两个对象,调用equals相等,hashCode就一定相等??? --> 对
                equals相等就是相同的对象,必须存储在同一个桶中,否则无法实现去重,所以要求必须根据成员变量的值重写hashCode的实现
        hashCode存在可以提高哈希表结构存储数据的效率,减少数据之间调用equals比较的次数,提高效率

可变参数:   ...
        1.参数的个数可以为0~n个,但是可变参数的类型要保持一致
        2.可变参数必须存在与参数列表的最后位置
        3.为可变参数构建一个数组,使用可变的参数的时候要使用数组的操作方式 

Map详解:

Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。

Map的遍历方式:
    1) keySet() 获取所有的key,得到一个Set集合
    2) values() 获取所有的value
    3) entrySet() 获取所有的键值对->entry->Set

HashMap :
    底层结构: 哈希表(数组+链表+红黑树)
    基于哈希表的Map接口的实现。并允许null值和null键

    新增功能: 无新增功能

初始容量Capacity: DEFAULT_INITIAL_CAPACITY = 1<<4 = 16  哈希表结构中的数组的默认初始长度
加载因子: loadFactor = DEFAULT_LOAD_FACTOR = 0.75f;
容量size : 集合中存储数据的个数
扩容临界值(阀值)threshold : size>Capacity*loadFactor -->resize()
扩容机制: 内部的数组为原容量的2倍

HashMap存储机制:
    数组的长度: 2的整数次幂
    1.根据key调用hash方法,计算出了key的hash值  int hash =  (h = key.hashCode()) ^ (h >>> 16)
    2.根据hash值计算位桶的索引 : index = (n - 1) & hash  优化的算法: 帮助提高效率,尽量减少哈希碰撞,散列的分布在每一个位桶中,提高效率
    3.判断数组table中对应索引位置table[index]==null,内部没有节点,当前要存储的键值对数据直接创建成为新节点new Node(hash, key, value, null)->放入数组index位桶中,作为链表头节点存在
    4.不等于null,从链表头开始遍历这个链表,判断每一个节点的key是否与要存储的键值对的key相等,如果相等value覆盖,都不相等,创建新节点,加入原链表的最后
    5.size++; if (++size > threshold) resize(); 判断如果>扩容临界值,进行扩容

在HashMap中,存储,value覆盖,去重等过程都是根据key计算的,只有在创建新节点|覆盖value值的时候,才与value有关系

定义一个HashMap存储键值对数据,key为学教师型Teacher类型,value为教师锁教授的学科,实现HashMap的去重原则(根据key做去重,value)
    key的类型需要重写hashCode与equals方法,因为HashMap的哈希表是根据key存储数据,根据key做去重

HashMap与Hashtable之间区别:
    1.继承体系不同
    2.null值要求不同
           HashMap->允许null值和null键
           Hashtable->键值对都不能为null
    3.同步问题
        HashMap:  线程不安全|不同步哈希表
        Hashtable: 线程安全|同步的哈希表
            内部方法上通过synchronized同步锁控制线程安全
    4.初始容量,扩容机制不同
          HashMap:
                初始容量 : 16
                扩容机制: 2倍
          Hashtable:
                初始容量 : 11
                扩容机制: 2倍+1   int newCapacity = (oldCapacity << 1) + 1;
     5.hash实现不同(求位桶的索引的方式不同)
            HashMap:  int hash =  (h = key.hashCode()) ^ (h >>> 16)
            Hashtable: int hash = key.hashCode();

TreeMap :
    底层结构: 红黑树
    特点: 默认升序排序(key)
    实现: 根据key做存储,根据做去重,根据key做排序
    TreeSet底层是由TreeMap维护的
    新增功能: 新增了一些与比较相关的方法
    去重: key的类型要求实现内部比较规则或者TreeMap对象构造器中指定外部比较规则
        优先找外部,没有外部找内部
    排序去重 : 都是根据比较器实现,与equals,hashCode没有关系

如何解决HashMap线程不安全?

1.使用Hashtable
2.使用Collections类的synchronizedMap(Map<K,V> m)
3.juc高级并发编程包下的 ConcurrentHashMap 线程安全的哈希表 --> 推荐

集合工具类

Collections 操作集合工具类  (Map集合无工具类)


    void sort(List) //对List容器内的元素排序,排序的规则是按照升序进行排序。
    void shuffle(List) //对List容器内的元素进行随机排列
    void reverse(List) //对List容器内的元素进行逆续排列
    void fill(List, Object) //用一个特定的对象重写整个List容器
    int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找特定对象


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值