文章目录
Set集合
概述和特点
1.元素存取无序
2.没有索引、只能通过迭代器或增强 for循环遍历
3.不能存储重复元素
哈希值
1.概述:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值;Object类中的public int hashCode():返回对象的哈希码值
2.特点:
- 同一个对象多次调用 hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的。而重写 hashCode()方法,可以实现让不同对象的哈希值相同
3.哈希表(具体理解见下方 保证元素唯一性原理)
HashSet集合
概述和特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通 for循环遍历
- 由于是 Set集合,所以是不包含重复元素的集合
保证元素唯一性原理
1.根据对象的哈希值计算存储位置,如果当前位置没有元素则直接存入,如果当前位置有元素存在,则进入第二步
2.当前元素的元素和已经存在的元素比较哈希值,如果哈希值不同,则将当前元素进行存储,如果哈希值相同,则进入第三步
3.通过equals()方法比较两个元素的内容,如果内容不相同,则将当前元素进行存储,如果内容相同,则不存储当前元素
HashSet 集合存储学生对象并遍历
建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对象
需要重写HashCode方法和equals方法
学生类:
package hashset;
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
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);
}
}
测试类:
package hashset;
import java.util.HashSet;
/*创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对象*/
public class HashSetDemo {
public static void main(String[] args) {
HashSet<Student> hs = new HashSet<Student>();
Student s1 = new Student("zy",20);
Student s2 = new Student("lx",21);
Student s3 = new Student("hh",22);
Student s4 = new Student("hh",22);
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
for(Student s:hs){
System.out.println(s.getName()+","+s.getAge());
}
}
}
LinkedHashSet集合
概述和特点:
- 哈希表和链表实现的 Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
Set集合排序
TreeSet集合
概述和特点
- 元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法
- TreeSet() :根据其元素的自然排序进行排序
- TreeSet(Comparator comparator) :根据指定的比较器进行排序
- 没有带索引的方法,所以不能使用普通 for循环遍历
- 由于是 Set集合,所以不包含重复元素的集合
自然排序Comparable
1.用 TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
2.自然排序,就是让元素所属的类实现 Comparable接口,重写compareTo(T o)方法
3.重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
public class Student implements Comparable<Student> {
private String name;
private int age;
...
@Override
public int compareTo(Student s) {
//num为正时,不用换顺序,为负,要换顺序,为0,不添加下一个,这个是从小到大,将this和s换一下就是从大到小
int num = this.age - s.age;
//比较年龄相同时,按照姓名排,这个是正序...
int num1 = num == 0 ? this.name.compareTo(s.name) : num;
return num1;
}
}
比较器排序Comparator
1.用 TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
2.比较器排序,就是让集合构造方法接收 Comparator的实现类对象,重写compare(T o1,T o2)方法
3.重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
//匿名内部类
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAge() - s2.getAge();
int num1 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
return num1;
}
});
泛型
泛型类
修饰符 class 类名<类型> { }
public class GeniricClass<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
//泛型类
GeniricClass<String> g1 = new GeniricClass<String>();
g1.setT("zy");
System.out.println(g1.getT());
GeniricClass<Integer> g2 = new GeniricClass<Integer>();
g2.setT(20);
System.out.println(g2.getT());
泛型方法
修饰符 <类型> 返回值类型 方法名(类型 变量名) { }
public class Geniric {
public <T> void show(T t){
System.out.println(t);
}
}
//泛型方法
Geniric g = new Geniric();
g.show("zy");
g.show(20);
泛型接口
修饰符 interface 接口名<类型> { }
public interface Geniric1<T> {
void show(T t);
}
public class GeniricImpl<T> implements Geniric1<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
Geniric1<String> g3 = new GeniricImpl<String>();
g3.show("zy");
GeniricImpl<Integer> g4 = new GeniricImpl<>();
g4.show(20);
类型通配符
类型通配符: <?>
- List<?> :表示元素类型未知的List,它的元素可以匹配任何的类型
这种带通配符的 List仅表示它是各种泛型List的父类,并不能把元素添加到其中
List<?> list1 = new ArrayList();
List<?> list2 = new ArrayList();
List<?> list3 = new ArrayList(); - 类型通配符上限: <? extends 类型>
List<? extends Number> :它表示的类型是Number或者其子类型 - 类型通配符下限: <? super 类型>
List<? super Number> :它表示的类型是Number或者其父类型
可变参数
1.格式:修饰符 返回值类型 方法名(数据类型… 变量名) { }
2.特点:
- 这里的变量其实是一个数组
- 如果一个方法有多个参数,包含可变参数,可变参数要放在最后
3.例子:sum求和:
public static void main(String[] args) {
System.out.println(sum(10,20));
System.out.println(sum(10,20,30));
System.out.println(sum(10,20,30,40));
}
public static int sum(int... a){
int sum = 0;
for(int i : a){
sum += i;
}
return sum;
}
4.应用:
- Arrays 工具类中有一个静态方法:
- public static List asList(T… a):返回由指定数组支持的固定大小的列表
- 返回的集合不能做增删操作,可以做修改操作
- List 接口中有一个静态方法:
- public static List of(E… elements):返回包含任意数量元素的不可变列表
- 返回的集合不能做增删改操作
- Set 接口中有一个静态方法:
- public static Set of(E… elements) :返回一个包含任意数量元素的不可变集合
- 在给元素的时候,不能给重复的元素
- 返回的集合不能做增删操作,没有修改的方法