2.8 Java之集合(Lish和Set)

集合概述

Java 集合也叫容器,util包下,用于存储对象,可分为 Collection 和 Map 两种体系

  • Collection接口:
    • Set:元素无序不可重复的集合 —类似高中的“集合”
    • List:元素有序可重复的集合 —”动态”数组
  • Map接口:具有映射关系“key-value对”的集合
    类似于函数 y = f(x) (x1,y1) (x2,y2),每个点就是键值对

Collection接口继承树

这里写图片描述

  • collection:接口,定义存储数据的功能,无直接实现类,定义了两个子接口
  • collections:工具类
  • 迭代器接口用于遍历集合里的元素
  • ArrayList类底层也是数组实现的
  • 主要6个实现类(SortedSet是接口)

Collection接口的方法

这里写图片描述

  • 第一行利用多态性,创建Collection接口的实现类对象
  • 123是包装类,添加方法的参数为对象
  • add方法参数为对象,addAll方法参数为集合类对象
  • Arrays为数组的工具类
  • asList方法返回collection的子接口list,这是数组转化为集合的一种方法

这里写图片描述
这里写图片描述
这里写图片描述

  • ArrayList类重写了ToString()方法,所以打印ArrayList,即打印其所有元素
  • 引申:
    • 要求集合里元素重写equals()方法(当元素的属性相同时,可认为是相同元素,而不是比较地址)
    • 若没重写,根据object类的equals方法,即比较地址值

这里写图片描述

  • containsAll方法即将集合元素每一个拿出来,进行contains比较,若出现一个则结果为false
  • retainAll方法实质取交集,改变了主动调用的集合

这里写图片描述
这里写图片描述

  • 哈希值决定存储位置,即栈空间通过该值指向堆空间区域
  • 黄色波浪线:未使用泛型
  • removeAll实质取两集合的差集,更改了主动调用的集合
  • toArray转化的数组类型为Object类型,因为集合存储的元素也是Object类型

这里写图片描述
- 返回一个迭代器接口实现类的对象
- 采用法三,因为现成的方法,上方有个多态性语句(别忘)


迭代总结

这里写图片描述

  • i看作指针,初始在第一个元素的上方
  • i.next():将指针向下移动并返回值

错误示范
这里写图片描述

问题:间隔打印+最后元素的后面为空

增强for循环

这里写图片描述
这里写图片描述

  • 冒号前:局部变量,集合中每个元素的类型
  • 每次取一个元素赋值给局部变量,不改变原始数据

for循环和增强for循环

这里写图片描述
这里写图片描述
输出结果
这里写图片描述

原因:每次取一个元素赋值给局部变量,不改变原始数据


List接口

总览:
这里写图片描述

  • Collection接口和Map接口并列
  • Properties子类用于处理属性文件

ArrayList类

这里写图片描述

  • 该类视作动态数组
  • List有序,所以可在指定位置添加
  • 打印list,元素位置是有序的
  • add()方法是添加,不是覆盖对应位置元素,后方元素依次后退
  • indexOf判断元素出现的位置,要重写equals方法,原因同以往章节

这里写图片描述
这里写图片描述

  • 截取子list是左闭右开

这里写图片描述
这里写图片描述

  • 打印list,元素有序性

LinkedList

  • 适合频繁的增加和删除操作
  • 不是数组结构,为链表结构

Vector

古老,处理速度缓慢,弃用吧


Set接口

Collection接口回顾

这里写图片描述

Set接口概述

这里写图片描述

  • 可添加null
  • 无序性!=随机性
  • 无序性指的是存储空间的无序性,存储位置根据哈希值,哈希算法要求可保证元素的唯一性,而List是开辟一整块连续区域
  • 哈希算法:不同元素的哈希值不同,类比坐位置,先hashcode找位置,没人直接坐,看有人占了座才调用equals方法比较
  • HashSet重写了ToString方法,打印引用即打印集合元素
  • 对于set:不可重复性要靠equals方法以及hashcode方法保证(缺一不可)
    意味着自定义的类加入Set,要重写上述两方法
  • 对于list:不可重复性只靠equals方法就行
  • hashcode方法要求属性值一样,则hash值一样,反之,亦如此
    hashcode与equals的一致性
  • hash值不同,直接存储,值相同,才调用equals方法比较

实例

这里写图片描述

能否加入Set集合,看hashcode方法,返回hash值不同,直接存储,值相同,才调用equals方法比较,属性又相同,才不存储

hashcode方法重写

这里写图片描述

  • hashcode的写法采用提供的迭代写法,不采用注释里的写法,原因:
    避免类似30+10=29+11的错误,违反了唯一性

LinkedHashSet

遍历顺序与添加顺序一致,因为链表维护添加顺序,并不能改变存储位置的无序性

原因如下
这里写图片描述

  • 三部分:前向索引,后向索引,值,即双向链表
    这里写图片描述

  • 遍历快,利用索引如水银泻地

  • 添加慢 要维护链表

TreeSet

这里写图片描述

  • 类似元素为String,包装类排序按从小到大(根据重写的Comparable接口内的方法)

自然排序

重写Comparable接口的方法
这里写图片描述

  • 上述方法若单单只比较一个属性,若两对象该属性一致,其他属性不一致,则后来的对象也不能添加到集合set中
  • 可利用String类型或包装类已重写的comparable接口内的方法
  • return 0很必要,不用抛异常的方法,return 0代表比较后元素的属性一致,即相同元素(实际可能未必),则不添加进set集合中
  • compareTo方法在Set中优先级高于hashcode和equals方法,换句话说set集合看 compareTo方法来判断是否添加入集合中

测试类
这里写图片描述

  • 要求set添加的对象为同一类(编译时不报错,运行时才报错),因为要比较属性
  • 关注遍历使用(Object str : set),因为Set集合的元素默认是Object类型,而add方法的实参虽然是String,但形参是Object类型,没有使用泛型的锅
  • person能否添加,全看 compareTo方法

定制排序

这里写图片描述

  • 少写一个方法(Comparator接口还有equals方法),因为类对象的根父类Object已经重写了equals方法
  • compare方法和上述compareTo方法内容一致,且都要求三位一体(注释解释)

简写如下(匿名内部类)
这里写图片描述


这里写图片描述

  • compare方法比较的是customer,只能添加customer
  • 每次添加对象时,自动找引用变量com对应的接口实现类的 compareTo方法

compare和compareTo辨析

  • 一个写在添加的类里,一个在添加的类外
  • 若添加的类可修改,则在类内部实现comparable接口
  • 若添加的类无法修改,则在类外部利用Comparator接口指定排序
  • 若两者都书写,最后定制排序优先于自然排序

TreeSet练习

MyDate类
这里写图片描述

  • 书写属性注意顺序,影响自动生成的构造器

Employee类
这里写图片描述
这里写图片描述


自然排序

这里写图片描述

实现接口
这里写图片描述
这里写图片描述


Equals与Hashcode方法

  • MyDate类的两方法:
    这里写图片描述

  • Employee类的两方法:
    这里写图片描述

  • equals仍要书写,会与collection接口的部分方法对应,比如contains,还是要调用equals方法

  • 先向mydate加入hashcode方法,再向employee添加hashcode

一个注意点
这里写图片描述

  • 若employee类不重写compareTo方法,则一个对象都添加不了(JDK7.0后)

测试类
这里写图片描述
输出结果
这里写图片描述

  • 不是按字母顺序,内部由hashcode排序,6次添加最后只加入5个元素,因为名字一样了(compareTo方法只看名字属性)

定制排序

这里写图片描述
这里写图片描述

  • 定制排序优先
  • 存入Set中的对象类型相同
  • int类型成员变量直接相减来判断大小
  • Set存储位置仍然是无序(hashcode决定存储位置)

猜你喜欢

转载自blog.csdn.net/lwz45698752/article/details/81268544
2.8