Set
Set
-
set系列集合特点
- 无序,不重复,无索引
- set集合的方法基本上和collectio的API一样
-
Set集合的实现类特点
- HasSet:无序,不重复,无索引
- LinkedHashSet:有序,不重复,无索引
- TreeSet:可排序,不重复,无索引
-
HashSet底层原理
-
底层原理详解:
1.创建一个默认长度16,默认加载因子为0.75(这个意思是当16*0.75的数组被填满时,这是数组就要扩容为原先的两倍)的数组,数组名为table
2.根据元素的哈希值跟数组的长度计算出英存入的位置
3.判断当前位置是否为null,是的话直接存入
4.不是,则表示有元素。则调用equals方法比较属性值:
- 属性值一样,则不存
- 不一样则存入数组,形成链表
- jdk8以前,新元素存入数组,老元素挂在新元素下面
- jdk8以后呢,新元素直接挂在老元素下面
- jdk8以后,当链表长度大于8,且数组长度大于等于64时,自动转为红黑树
-
HashSet集合底层采取哈希表存储数据
-
哈希表是一种对于增删改查数据性能都有比较好的结构
-
哈希表组成:
- jdk8之前:数组加链表
- jdk8之后:数组+链表+红黑树
-
-
哈希值:
- 根据HashCode方法算出来的int类型的整数
- 该方法定义在object类中,所有对象都可以调用,默认使用地址值继续计算
- 一般情况下,会重写hashcode方法,利用对象内部的属性值计算哈希值
-
对象的哈希值特点
-
如果没有重写hashcode方法,不同对象计算出的哈希值是不同的
-
如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
package A01Set; public class HashSetDemo01 { public static void main(String[] args) { /* 哈希值: 对象的整数表现形式 1.如果没有重写hashcode方法,不同对象算出的哈希值是不同的 2.如果已经重写hashcode方法,不同的对象只要属性值想相同,计算出的哈希值就是一样的 3.但是在小部分情况下,不同的属性值或不同的地址值计算出来的哈希值可一样,这叫哈希碰撞 */ //1.创建对象 Student s1=new Student("zhangsan",23); Student s2=new Student("zhangsan",23); //2. System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println("abc".hashCode()); System.out.println("acD".hashCode()); } }-
封装
package A01Set; import java.util.Objects; public class Student { private String name; private int age; public Student(){} public void setName(String name) { this.name = name; } public Student(String name,int age){ this.name=name; this.age=age; } public String getName() { return name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }1.为什么hashset的存取顺序不一样
答:因为取的时候为从数组的0索引开始一个个检阅,当某个数组位置有链表时,再一个一个读取链表里的东西,而存放的时候是要根据hashcode方法算出哈希值存入的,不是按照索引的方式
2.HashSet为什么没有索引
答:因为HashSet不够纯粹,它是由数组+链表+加红黑树构成的,所以数组有索引的地方且有链表,但一个数组索引不能够代表链表里所有的对象,所以没有索引
3.HashSet是利用什么机制保证数据去重的
答:1.hashcode方法计算哈希值,哈希值确定当前元素存储位置
2.equals方法,对比内部的属性值是否相同
3.如果存入的是自定义对象,那一定要重写这俩个方法
-
-
package A01Set;
import java.util.HashSet;
/*
需求:创建一个存储学生对象的集合,存储多个学生对象
使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是一个对象*/
public class HashDemo02 {
public static void main(String[] args) {
//1.创建对象
Student s1=new Student("zhangsan",23);
Student s2=new Student("lisi",24);
Student s3=new Student("wangwu",25);
Student s4=new Student("zhangsan",23);
//2.创建集合添加学生
HashSet<Student> ha=new HashSet<>();
//3.添加元素
System.out.println(ha.add(s1));
System.out.println(ha.add(s2));
System.out.println(ha.add(s3));
System.out.println(ha.add(s4));
//4.打印集合
System.out.println(ha);
}
}
-
LinkedHashSet底层原理
-
有序,不重复,无索引
-
底层数据结构依然是哈希表,只是每个元素有额外的多了一个双链表的机制记录存储的顺序
package A01Set; import java.util.LinkedHashSet; public class LinkeHashset { public static void main(String[] args) { //1.创建对象 Student s1=new Student("zhangsan",23); Student s2=new Student("lisi",24); Student s3=new Student("wangwu",25); Student s4=new Student("zhangsan",23); //2.创建集合 LinkedHashSet<Student> lh=new LinkedHashSet<>(); //3.添加元素 System.out.println(lh.add(s1)); System.out.println(lh.add(s2)); System.out.println(lh.add(s3)); System.out.println(lh.add(s4)); //4.打印集合 System.out.println(lh);-
以后要数据去重,使用哪个
默认使用hashSet
如果有要求去重且有序,才使用LinkedHashSet
-
-
-
TreeSet(底层是红黑树)
-
不重复,无索引,可排序
-
可排序:按照元素的默认规则(由小到大)排序
-
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都比较好
-
TreeSet集合默认的规则:
- 对于数值类型1:integer,double默认按照从小到大的顺序进排序
- 对于字符字符串类型:按照字符在ASCii码表中数字升序进行排序
-
TreeSet的两种比较方式
-
方式一:默认排序/自然排序:Javabean类实现Comparable接口指定比较规则
-
public int compareTo(Student o) { System.out.println("--------------------"); System.out.println("this:"+this); System.out.println("o"+o); //指定排序的规则 //只看年龄,我想要按照年龄的升序进行排列 return this.getAge()-o.getAge(); } -
package A01Set; import org.w3c.dom.ls.LSOutput; import java.util.TreeSet; public class TreeSetDemo02 { //自定义类使用treeset,该如何比较的问题 public static void main(String[] args) { //1.创建三个学生对象 Student s1 = new Student("zhangsan", 23); Student s2 = new Student("lisi", 24); Student s3 = new Student("wangwu", 25); //2,创建集合对象 TreeSet<Student> ts = new TreeSet<>(); //3.添加元素 ts.add(s3); ts.add(s2); ts.add(s1); //4.打印集合 System.out.println(ts); //TreeSet底层是红黑树 } } -
方式二:比较器排序,
-
-
package A01Set;
public class Student2 implements Comparable<Student2> {
private String name;
private int age;
private int Chinese;
private int Math;
private int English;
public Student2(){}
public Student2(String name, int age, int Chinese, int Math, int English) {
this.name=name;
this.age=age;
this.Chinese=Chinese;
this.Math=Math;
this.English=English;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getChinese() {
return Chinese;
}
public void setChinese(int chinese) {
Chinese = chinese;
}
public int getMath() {
return Math;
}
public void setMath(int math) {
Math = math;
}
public int getEnglish() {
return English;
}
public void setEnglish(int english) {
English = english;
}
@Override
public String toString() {
return "Student2{" +
"name='" + name + '\'' +
", age=" + age +
", Chinese=" + Chinese +
", Math=" + Math +
", English=" + English +
'}';
}
@Override
public int compareTo(Student2 o) {
int sum1=this.getChinese()+this.getMath()+this.getEnglish();
int sum2=o.getChinese()+o.getMath()+o.getEnglish();
int i=sum1-sum2;
i=i==0?this.getChinese()-o.getChinese():i;
i=i==0?this.getMath()-o.getMath():i;
i=i==0?this.getEnglish()- o.getEnglish():i;
i=i==0?this.getAge()-o.getAge():i;
return i;
}
}
package A01Set;
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetDemo03 {
public static void main(String[] args) {
/**
* 需求:请自行选择比较器排序和自然排序两种方式
* 要求:存入四个字符”c“,”ab“,”df“,QWER
* 按照长度排序,如果一样则按照首字符排序
*
* 采取第二种排序方式:比较器排序
*
*/
//1.创建集合对象
TreeSet<String> ts=new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int i=o1.length()-o2.length();
i=i==0?o1.compareTo(o2):i;
return i;
}
});
//2.添加元素
ts.add("c");
ts.add("ab");
ts.add("df");
ts.add("qwer");
//3.打印集合
System.out.println(ts);
}
}
package A01Set;
import java.util.TreeSet;
//实际问题练习
public class TreeSetDemo04 {
public static void main(String[] args) {
/*
*按照总分从高到低输出到控制台
* 如果总分一样,按照语文排序
* 如果语文一样,按照数学排序
* 如果数学一样,按照英语排序
* 如果都一样,按照年龄排序
* 如果都一样,则认为是一个学生,不存
*
*/
//1.创建对象
Student2 s1=new Student2("zhangsan",23,90,99,50);
Student2 s2=new Student2("lisi",24,90,98,50);
Student2 s3=new Student2("wangwu",25,95,100,30);
Student2 s4=new Student2("zhaoliu",26,60,99,70);
Student2 s5=new Student2("zhangsan",27,70,80,70);
//2.创建集合
TreeSet<Student2> ts=new TreeSet<>();
//3.添加元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
//4.打印集合
for (Student2 t : ts) {
Systym.out.println(t);
}
}
}
-
方法返回值的特点:
-
负数:表示当前要添加的元素是小的,存左边
-
正数
package A01Set; import java.util.TreeSet; public class TreeSetDemo04 { public static void main(String[] args) { /* *按照总分从高到低输出到控制台 * 如果总分一样,按照语文排序 * 如果语文一样,按照数学排序 * 如果数学一样,按照英语排序 * 如果都一样,按照年龄排序 * 如果都一样,则认为是一个学生,不存 * */ //1.创建对象 Student2 s1=new Student2("zhangsan",23,90,99,50); Student2 s2=new Student2("lisi",24,90,98,50); Student2 s3=new Student2("wangwu",25,95,100,30); Student2 s4=new Student2("zhaoliu",26,60,99,70); Student2 s5=new Student2("zhangsan",27,70,80,70); //2.创建集合 TreeSet<Student2> ts=new TreeSet<>(); //3.添加元素 ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); //4.打印集合 for (Student2 t : ts) { System.out.println(t); } } }
-
-
方法返回值的特点:
- 负数:表示当前要添加的值是小的,存左边
- 整数:表示当前要添加的元素是大的,存右边
- o🚴表示当前要添加的元素已经存在,舍弃
1.如果想要集合中的元素可重复
- 用ArrayList集合,基于数组的(用的最多
2.如果想要集合中的元素可重复,而且当前的增删操作明显多于查询
- 用LinkedList集合,基于链表
3.如果想对集合中的元素去重
- 用Hash Set集合,基于哈希表的
4.如果想对集合中的元素去重,且保证存取顺序
- 用LinkedHashSet集合,基于哈希表和双链表,效率低于HashSet
5.如果相对集合中的元素进行排序
- 用TreeSet集合,基于红黑树,后续也可以用List集合实现排序
Map
-
Map接口特点
- 用于存储任意键对值(key—vAlue)
- 键:无序,无下标,不允许重复
- 值:无序,无下标,可重复
-
Map父接口:存储一对数据,无序,无下标,键不可重复,值可重复
-
package A01Set; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo01 { public static void main(String[] args) { //1.创建一个Map集合 Map<String,String> ma=new HashMap<>(); //2.添加元素 ma.put("cn","中国"); ma.put("uk","英国"); ma.put("usa","美国"); System.out.println("元素个数:"+ma.size()); System.out.println(ma.toString()); //3.删除 //ma.remove("usa"); //System.out.println(ma); //4.遍历 //3.1使用KeySet() System.out.println("----------keyset()-----------"); Set<String> keyset=ma.keySet(); for (String key : keyset) { System.out.println(key+"--------"+ma.get(key)); } //3.2使用entrySet Set<Map.Entry<String,String>> entries=ma.entrySet(); for (Map.Entry<String, String> entry : entries) { System.out.println(entry.getKey()+"------"+entry.getValue()); } } } -
hashmap
-
package A01Set; import java.util.HashMap; import java.util.Map; public class HashMapDemo01 { public static void main(String[] args) { /* HashMap集合的使用 存储结构:哈希表(链表加红黑树 */ //1.创建集合 HashMap<Student3,String> ha=new HashMap<Student3,String>(); //2.创建对象 Student3 s1=new Student3("孙悟空",100); Student3 s2=new Student3("孙悟能",101); Student3 s3=new Student3("孙悟静",102); //3.添加val值 ha.put(s1,"齐天大圣"); ha.put(s2,"天蓬元帅"); ha.put(s3,"大进军"); //4.打印 System.out.println("元素个数"+ha.size()); System.out.println(ha.toString()); //5.遍历 for (Student3 key : ha.keySet()) { System.out.println(key.toString()+"--------"+ha.get(key)); } //entryset for (Map.Entry<Student3, String> entries : ha.entrySet()) { System.out.println(entries.getKey()+"----"+entries.getValue()); } //4.判断 System.out.println(ha.containsKey(s1)); } } -
package A01Set; import java.util.Objects; public class Student3 { private String name; private int stuNo; public Student3(String name,int stuNo) { this.name = name; this.stuNo=stuNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getStuNo() { return stuNo; } public void setStuNo(int stuNo) { this.stuNo = stuNo; } @Override public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; Student3 student3 = (Student3) o; return stuNo == student3.stuNo && Objects.equals(name, student3.name); } @Override public int hashCode() { return Objects.hash(name, stuNo); } @Override public String toString() { return "A01Set.Student3{" + "name='" + name + '\'' + ", stuNo=" + stuNo + '}'; } }
-
Collections工具类
package A01Set;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo01 {
public static void main(String[] args) {
//1.创建集合
List<Integer> list=new ArrayList<>();
//2.添加元素
list.add(20);
list.add(5);
list.add(16);
list.add(8);
//3.sort排序
System.out.println("排序之前:"+list.toString());
Collections.sort(list);
System.out.println("排序之后:"+list.toString());
//4.二分查找
int i=Collections.binarySearch(list,5);
System.out.println(i);
//copy
List<Integer> dest=new ArrayList<>();
for(int k=0;k<list.size();k++){
dest.add(0);
}
Collections.copy(dest,list);
System.out.println(dest.toString());
//反转reverse
Collections.reverse(list);
System.out.println("反转之后"+list.toString());
//打乱shuffle
Collections.shuffle(list);
System.out.println("大乱之后"+list.toString());
}
}

浙公网安备 33010602011771号