set集合特点:
- 无序(元素顺序与放入顺序无关),不能按索引访问元素
- 不可重复(集合中不允许出现重复的元素)
实现类:HashSet、TreeSet
1. HashSet(相对无序存储,不可以存储相同元素(排重),通过哈希表实现的集)
此类实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null元素。
Hash:哈希——实际含义散列,就是一种算法,把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值。
哈希表:数组加链表,既有数组的优点也有链表的优点。
HashSet的去重原理
第一步:先判断你说添加的对象和set集中对象的hashCode()有没有相同的,如果没有,则直接添加进
去,如果有相同的hashCode()方法的返回值,则进行第二步
第二步:此时再去将两个相同hashCode方法相同的对象,去执行equals判断,如果返回的是true,那么此
时就会判断这两个对象是重复值,那么第二个就不能添加了,如果是false,那就可以添加
因此,向Set集合中添加元素时,需要重写hashCode()和equals()方法,防止相同元素被添加到Set集合中
重写hashCode()
hashCode()是Object中的方法,每个对象的hashCode值是唯一的,所以可以理解成hashCode值表示这个对象在内存中的位置,字符串String的hashCode(),是根据内容计算的。
重写equals()
equals()方法是Object类中的方法,表示比较两个对象是否相等,若不重写相当于比较对象的地址,
所以我们可以尝试重写equals方法,检查是否排重。
2.TreeSet
TreeSet是用于对元素进行排序的有序集合类,不允许有重复的元素,不保证元素顺序与插入顺序一致
- 数据结构:二叉树
- 特点:元素是有大小顺序的
TreeSet会对元素进行排序,排序的依据:
元素本身具有的自然顺序,当不可自己排序时:
1.让JavaBean实现`Comparable`接口,实现compareTo()方法,让对象自身具有可比较性
2.提供一个比较器,根据比较器进行排序
定义一个比较器,实现`Comparator`接口的类,实现compare()方法
在创建TreeSet时传入比较器
3.匿名内部类,重写compare()方法
TreeSet判断重复的依据:当添加的两个元素的compareTo()返回值为0时,则认为是相同元素
Map集合特点
Map是专门用来处理 键值映射数据 的一种集合,可以根据key键实现对value值的操作
- 是一种映射关系,称为键值对(key-value)
- key必须是唯一,不允许重复
- 一个key只能对应一个value,但一个value可以有多个key与之对应
- 不保证元素的顺序与插入的顺序一致,不能按索引访问元素
实现类:HashMap、Hashtable、Properties
1. HashMap
基于哈希表的Map接口的实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序。
存储特点:
相对无序存储,元素以键值对形式存在,键不可以重复,值可以重复,元素整体排重,可以快速的通过键查找到所对应的值,通过哈希表实现的集合。
从底层中了解到,HashSet就是HashMap的键,所以HashSet的去重规则也适用我们HashMap的键去重(重写hashCode()和equals方法)
Map集合的排重,只需要重写键所属的类的hashCode和equals方法即可。
map集合中若向集合中添加相同键的键值对时,新的值会将旧的值覆盖。
上述代码中map集合中有两个键值对,分别为:张三-12---二哈,lisi-12---旺财
遍历HashMap的三种方式:
- 通过keySet()获取所有key的集合,然后遍历所有的key
- 通过values()获取所有value的集合,然后遍历所有的value
- 通过entrySet()获取所有的key-value的集合,然后遍历所有的key-value键值对
HashMap<Integer, Student> map = new HashMap<Integer, Student>();
Student stu1 = new Student(1001, "tom");
Student stu2 = new Student(1002, "jack");
Student stu3 = new Student(1003, "mike");
// 将学号作为key,将学生对象作为value
map.put(stu1.getNo(), stu1);
map.put(stu2.getNo(), stu2);
map.put(stu3.getNo(), stu3);
// Map本身无法遍历
/*
* 方式1:遍历所有的key
*/
Set<Integer> keys = map.keySet(); // 返回所有kery的集合
for (Integer key : keys) {
Student value = map.get(key);
System.out.println("key:" + key + ",value:" + value);
}
System.out.println("--------------------------------");
/*
* 方式2:遍历所有的value
*/
Collection<Student> values = map.values();
for (Student value : values) {
System.out.println(value);
}
System.out.println("--------------------------------");
/*
* 方式3:遍历所有的key-value
* Map.Entry就表示key-value
* 返回一个Set集合,Set集合的泛型是Map.Entry类型
* Map.Entry的泛型是Map集合的泛型
*/
Set<Map.Entry<Integer, Student>> entries = map.entrySet();
Iterator<Entry<Integer, Student>> it = entries.iterator();
while(it.hasNext()){
Entry<Integer, Student> entry = it.next(); //获取Entry(key、value)
Integer key = entry.getKey();
Student value = entry.getValue();
System.out.println("key:"+key+",value:"+value);
}