package com.Set;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
/*
* Set接口
* 实现Collection接口,无序,唯一
* 不是真的无序,是按照一种特殊的算法存储的,但不是11排列这种顺序
*
* HashSet
* 底层是哈希表,哈希表示元素为链表的数组结构
* hashSet唯一,所以添加不进重复元素,观察其源码,发现其底层是hashMap,其add方法和hashCode()和equals()方法有关
* 只有当两个元素的hash值相等,并且equals方法为true的时候才会直接跳过这个添加以保证hashSet集合的唯一性
*
* 可以发现,前面好像是有唯一性,使用对象的时候就失效了,这是为什么呢?
* 因为String对象自动重写了hashCode和equals方法,比较的是值。而你的Student对象的两个方法都没有重写,比较的就
* 是Object对象的hashCode方法得到的值,也就是地址值的特殊表示。所以,你只有将对象的equals和hashCode方法重写后才能
* 使得hashSet的唯一性生效
* 此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
* LinkedHashSet
* 具有可预知的迭代顺序,LinkedHashSet的子类
* 底层是哈希表和链表
* 哈希表保证元素唯一性
* 链表保证元素有序(存储一致)
*/
/*
* 首先比较哈希值是否相同
* 相同: 继续执行equals
* 返回true:元素重复了,不添加
* 返回false:可以添加
* 不同:也可以添加
*/
public class HashSetAndLinkedHashSet {
public static void main(String[] args) {
LinkedHashSet<String> hs=new LinkedHashSet<String>();
hs.add("hello");
hs.add("java");
hs.add("world");
hs.add("java");
hs.add("world");
for(String s:hs){
System.out.println(s);
}
}
public void test01(){
Set<String> s=new HashSet<String>();
s.add("java");
s.add("hello");
s.add("world");
s.add("java");
s.add("hello");
for(String ss:s){
System.out.println(ss);
}
Set<Student> s1=new HashSet<Student>();
s1.add(new Student("林青霞",27));
s1.add(new Student("范冰冰",30));
s1.add(new Student("林青霞",27));
s1.add(new Student("柳岩",25));
s1.add(new Student("林青霞",27));
for(Student ss:s1){
System.out.println(ss);
}
}
}
package com.Set;
public class Student implements Comparable<Student>{
private String name;
private int 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;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Student() {
super();
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
//两个Student对象的比较方法
//我这里定义它先根据年龄比较,然后根据姓名比较
if(this.equals(o)){
return 0;
}else if(this.getAge()==o.getAge()){
return this.getName().compareTo(o.getName());
}else{
return this.getAge()-o.getAge();
}
}
}
package com.Set;
import java.util.Comparator;
import java.util.TreeSet;
/*
* TreeSet:能够对元素按照某种规律排序
* TreeSet的排序方式和它的比较方式有关
*
* 底层是红黑树结构!
*
* 排序有两种:
* A:自然排序
* B:比较器排序
*
* 构造方法:
* TreeSet() 构造新的空set,根据自然顺序进行排序
* TreeSet(Comparator<? extends E> o) 构建一个空的TreeSet,它根据比较器进行排序
* TreeSet集合的特点:
* 排序和唯一
* 唯一:根据比较的值是否为0
* 排序:数的存储方式和取出方式
*
* 自然排序接口:Comparable 在基本数据类型和常用类型都有它的实现,它表现在类型的compareTo方法上:
* Number型比较的是数值的大小,String比较的是内容的哈希吗,boolean类型真比假为正,假比真为负,其他为0,char类型比较的是Ascill码
* 如果你使用的是自定义对象类型,就必须实现Comparable接口,才能使用自然排序。
* 自然排序,就是依据对象的compareTo方法进行排序
*
* 比较器排序
* 什么是比较器?
* 比较器是一个用来比较两个同类型对象的对象,比较器实现了Comparator接口,在compare方法中确定如何比较或者说是比较结果。
*
* 使用比较器就是在构造方法中加入比较器。
*
* 使用比较器与自然排序相比:
* 自然排序的比较方式是定义在对象里的,所以每一个同类型的对象的比较方法都是确定的。而比较器是独立的一个对象,在需要这样比较的时候调用特定的比较器就好。
*/
public class TreeSetStudy {
public static void main(String[] args) {
//我们前面使用了自然排序,那么怎么使用比较器排序呢?
TreeSet<Student> ts=new TreeSet<Student>(new comparator02());
ts.add(new Student("林青霞",27));
ts.add(new Student("刘亦菲",18));
ts.add(new Student("苏有朋",30));
ts.add(new Student("刘诗诗",18));
for(Student i:ts){
System.out.println(i);
}
}
public void test01(){
TreeSet<Integer> ts=new TreeSet<Integer>();
ts.add(18);
ts.add(28);
ts.add(22);
ts.add(18);
ts.add(19);
for(int i:ts){
System.out.println(i);
}
}
public void test02(){
//自然排序
TreeSet<String> ts=new TreeSet<String>();
ts.add("hi");
ts.add("nice");
ts.add("to");
ts.add("meet");
ts.add("you");
for(String s:ts){
System.out.println(s);
}
}
public void test03(){
//这样报错:com.Set.Student cannot be cast to java.lang.Comparable
//因为这样默认使用的是自然排序,但是Student并没有实现Comparable接口,没有自然比较方法,接下来我们让Student实现Comparable接口试试
TreeSet<Student> ts=new TreeSet<Student>();
ts.add(new Student("林青霞",27));
ts.add(new Student("刘亦菲",18));
ts.add(new Student("苏有朋",30));
ts.add(new Student("刘诗诗",18));
for(Student i:ts){
System.out.println(i);
}
}
public void test04(){
TreeSet<Integer> ts=new TreeSet<Integer>(new comparator01());
ts.add(18);
ts.add(28);
ts.add(22);
ts.add(18);
ts.add(19);
for(int i:ts){
System.out.println(i);
}
}
}
class comparator01 implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
int i=o2-o1;
return i;
}
}
class comparator02 implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
if(o1.getAge()!=o2.getAge()){
return o2.getAge()-o1.getAge();//年龄从大到小排序
}else{
return o1.getName().compareTo(o2.getName());
}
}
}
package com.Set;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
/*
* ctrl+ shift+ o 自动导包
* alt+ shift +s+o 有参构造
* alt+ shift +s+c 无参构造
* alt+ shift +s+r 封装
*/
public class TreeSetDemo {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//内部类实现比较
TreeSet<Student01> ts=new TreeSet<Student01>(new Comparator<Student01>(){
@Override
public int compare(Student01 o1, Student01 o2) {
//总分从高到低
int num=o2.getSum()-o1.getSum();
//总分相同的语文不一定相同
int num2=num==0?o1.getChinese()-o2.getChinese():num;
//数学不一定相同
int num3=num2==0?o1.getMath()-o2.getMath():num2;
//英语不一定相同
int num4=num3==0?o1.getEnglish()-o2.getEnglish():num3;
//姓名不一定相同
int num5=num4==0?o1.getName().compareTo(o2.getName()):num4;
return num5;
}
});
for(int x=1;x<=5;x++){
System.out.println("请输入第"+x+"个学生的姓名:");
String name=sc.nextLine();
System.out.println("请输入第"+x+"个学生的语文成绩:");
String chineseString=sc.nextLine();
System.out.println("请输入第"+x+"个学生的数学成绩:");
String mathString=sc.nextLine();
System.out.println("请输入第"+x+"个学生的英语成绩:");
String englishString=sc.nextLine();
Student01 s=new Student01();
s.setName(name);
s.setChinese(Integer.parseInt(chineseString));
s.setMath(Integer.parseInt(mathString));
s.setEnglish(Integer.parseInt(englishString));
ts.add(s);
}
System.out.println("学生信息录入完毕");
System.out.println("学生信息从高到低顺序如下:");
System.out.println("姓名 语文成绩 数学成绩 英语成绩");
for(Student01 s:ts){
System.out.println(s.getName()+" "+s.getChinese()+" "+s.getMath()+" "+s.getEnglish());
}
}
}
class Student01{
private String name;
private int chinese;
private int math;
private int english;
public Student01(String name, int chinese, int math, int english) {
super();
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}
public Student01() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
public int getSum(){
return getChinese()+getMath()+getEnglish();
}
}