目录
知识点1、Set集合
Set系列集合特点
没有索引
元素不可以重复
存储和取出没有顺序
Set集合实现类
HashSet : 不重复、无索引、存储和取出没有顺序。
LinkedHashSet: 有序、不重复、无索引。
TreeSet: 排序、不重复、无索引。
HashSet
HashSet集合概述和特点
无索引: 没有带索引的方法,所以不能使用普通for循环遍历
不重复: 由于是Set集合,所以元素唯一
存储和取出没有顺序: 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致。
(注意:这里的无序并不代表随机。)
底层数据结构是哈希表
哈希表存储元素的过程
根据hashCode值计算元素存放的位置
如果这个位置没有元素,直接存储
如果这个位置有元素,调用equals比较
equals()为false,存储
equals()为true,不存储(认为是相同的元素)
如果希望HashSet集合认为2个内容相同的对象是重复的应该怎么办?
重写对象的hashCode()和equals()方法。
Object类中有一个方法可以获取对象的哈希码值
public int hashCode():返回对象的哈希码值
默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以让对象的哈希值和对象的属性相关。
ArrayList类需不需要重写hashCode() 和 equals()方法?
不需要,ArrayList 底层结构是一个数组,可以存储重复的内容
而SetList底层结构是一个哈希表,长度固定为16,判断存储位置需要hashCode()方法,当判断位置相同的时候,需要equals()方法判断内容是否相同
LinkedHashSet
有序、不重复、无索引。
这里的有序指的是保证存储和取出的元素顺序一致( 按照写入的顺序)
原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
TreeSet(几乎不用)
不重复、无索引、可排序
可排序:按照元素的大小默认升序(由小到大)排序。
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
注意:TreeSet集合是一定要排序的,可以默认排序,也可以将元素按照指定的规则进行排序。
默认排序
1.对于数值类型:Integer , Double,官方默认按照大小进行升序排序。
2.对于字符串类型:默认按照首字符的编号升序排序,如果首字母相同,就按照第二个字符进行升序排序,依次下去
3.对于自定义类型如Student对象,TreeSet无法直接排序,需要制定排序规则
TreeSet集合存储对象的的时候有2种方式可以设计自定义比较规则
方式一 (比较器排序Comparator)
TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则。(常用)
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// o1计算总分
double sum1 = o1.getChinese() + o1.getMath() + o1.getEnglish();
// o2计算总分
double sum2 = o2.getChinese() + o2.getMath() + o2.getEnglish();
// 先比较总分,如果总分相同,比较姓名
int x = (int)(sum2 - sum1);
if (x == 0) {
x = o1.getName().compareTo(o2.getName());
}
return x;
}
});
方式二 (自然排序Comparable)
让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则。
// 元素的自然排序,就是让类实现Comparable接口
public class Student implements Comparable<Student> {
private String name;
private double chinese;
private double math;
private double english;
// 元素的自然排序
@Override
public int compareTo(Student o) {
// this 和 o
return (int)(o.math - this.math);
}
}
第一个元素减第二个元素升序。
第二个元素减第一个元素降序。
第一个元素等于第二个元素,此时Treeset集合只会保留一个元素,认为两者重复。
基本数据类型就是 o1 - o2
引用数据类型就是 o1.compareTo(o2)
自然排序和比较器排序同时存在,优先使用比较器
知识点2、可变参数
什么是可变参数
JDK1.5推出的新特性,参数的数量可以变化,类型相同。
如果方法需要接收多个参数,并且多个参数类型一致,可以使用可变参数。
public class Demo081 {
public static void main(String[] args) {
int r = add(1, 3, 6, 8);
System.out.println(r);
}
// 可变参数的本质是一个数组
public static int add(int... x) {
System.out.println(x); // [I@880ec60
int sum = 0;
for (int number : x) {
sum += number;
}
return sum;
}
}
注意事项:
1.一个方法中只能有一个可变参数
2.可变参数需要在参数列表的最后面
3、可变参数的本质是一个数组
知识点3、Collections工具类
Collections的API只能针对于List集合排序
Set集合的存储和取出是无序的,调用Collections中的排序方法毫无意义
知识点4、Map键值对(映射)
Map集合的每个元素是键值对:key=value(键值对元素)。
Map集合体系特点
Map集合的每个元素是键值对:key=value(键值对元素)。
Map不能包含重复的键。
个键对应一个值。
Map集合实现类特点
HashMap:元素按照键不重复,无索引,存储和取出无顺序。
LinkedHashMap:元素按照键不重复,无索引,存储和取出有顺序。
TreeMap:元素按照键排序,不重复,无索引的。
注意:
put()方法
如果内容不存在就添加数据
如果内容存在就顶替数据(后面的值顶替前面的值)
HashMap
Map集合的遍历方法
方法1、键找值
public class Demo13 {
public static void main(String[] args) {
HashMap<String, String> hm = new HashMap<>();
hm.put("a", "A");
hm.put("b", "B");
hm.put("c", "C");
hm.put("d", "D");
// 键找值的遍历方式
// 1.得到所有的键
Set<String> keySet = hm.keySet();
// 2.遍历得到每个键
for (String key : keySet) {
// 3.通过键找值
String value = hm.get(key);
System.out.println(key + " :: " + value);
}
}
}
方法2、键值对
(建议使用键值对的方式,Map的底层就是键值对存储,效率更高)
public class Demo14 {
public static void main(String[] args) {
HashMap<String, String> hm = new HashMap<>();
hm.put("a", "A");
hm.put("b", "B");
hm.put("c", "C");
hm.put("d", "D");
// 1.获取所有的Entry
Set<Map.Entry<String, String>> entrySet = hm.entrySet();
// 2.遍历取出每个Entry
for (Map.Entry<String, String> entry : entrySet) {
// 3.获取键和值
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + " == " + value);
}
}
}
HashMap的特点
HashMap底层是哈希表结构的
依赖hashCode()方法和equals()方法保证键的唯一
如果键要存储的是自定义对象,需要重写hashCode()和equals()方法
LinkedHashMap
链表和哈希表组合的一个数据存储结构
输出和存储有顺序
与LinkedHashSet类似
TreeMap
由键决定特性:不重复、无索引、可排序
可排序:按照键数据的大小默认升序(有小到大)排序(只能使用键排序。)
TreeMap跟TreeSet一样底层是红黑树结构的。
注意: TreeMap集合是一定要排序的,否则会报错
TreeMap 的排序是按照 键 来进行排序的