[1]HashSet
import java.util.*;
/*
* Set:无序不可重复
* HashSet:线程不安全的,底层是哈希表
* TreeSet:线程不安全的,底层是二叉树
*
*
* HashSet:如何去重
* 原理:是在添加元素时,add()方法调用元素的hashCode()和equals方法实现去重,首先分别调用元素所属类的hashCode()方法
* 比较两个对象的哈希码值,如果不同,直接认为是不同对象,不再去调用equals方法,如果相同
* 再继续调用equals方法,返回true认为是一个对象,返回false认为是两个对象。
*
* 实例:使用HashSet实现Person对象的存储
* 比较规则自己制定:按照年龄和姓名比,相同则认为是一个人
* 分析:要重写hashCode和equals方法
*
*/
class Person{
int age;
String name;
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
public int hashCode()
{
return name.hashCode()+age*10000;//自己写的规则
}
public boolean equals(Object obj) {
if(!(obj instanceof Person))//在用集合的add方法添加元素时,调用的是新添加的元素的hashCoce()方法,如果相同再调用新添加
//的元素的equals方法,把前一个元素作为参数传进来,两个元素可能是不同类型的,所以需要这个类型的判断
throw new ClassCastException("Person类型转换异常");
Person p=(Person)obj;
if(p.name==name&&p.age==age)
return true;
else
return false;
}
}
class Dog{
int age;
String name;
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Dog(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Dog() {
super();
}
public int hashCode()
{
return name.hashCode()+age*10000;
}
public boolean equals(Object obj) {
if(!(obj instanceof Dog))
throw new ClassCastException("Dog类型转换异常");
Dog p=(Dog)obj;
if(p.name==name&&p.age==age)
return true;
else
return false;
}
}
public class Demo3 {
public static void main(String[] args) {
//在add方法的内部实现的去重功能,默认调用的元素的hashCode()和equals()方法
//String内部已经重写了hashCode()和equals()方法
HashSet set=new HashSet<>();
set.add("java");
set.add("php");
set.add("php");
set.add("python");
set.add("html");
set.add("BigData");
System.out.println(set);//无序是指:顺序是按照系统内部的规定进行排序的,人无法预知
HashSet set1=new HashSet<>();
//set1.add(new Dog("bingbing",10));//使用这句会产生异常
set1.add(new Person("bingbing",10));
//因为Person对象的hashCode和Dog的相同,就调用用Person的equals方法
//把前面Dog对象作为参数传进来。类型不对产生异常
set1.add(new Person("bingbing",107));
set1.add(new Person("bingbing",109));
set1.add(new Person("bingbing",10));
System.out.println(set1);//无序是指:顺序是按照系统内部的规定进行排序的,人无法预知
}
}
输出:
[python, java, php, BigData, html]
[Person [name=bingbing, age=107], Person [name=bingbing, age=109], Person [name=bingbing, age=10]]
[b]TreeSet--通过实现Comparable接口,重写CompareTo方法实现TreeSet的排重有序
import java.util.*;
/*
* 实例:在TreeSet中存入Person1类的对象
* 并按照年龄和姓名实现排序,去重
* 分析:需要实现Comparable接口中的compareTo方法
*/
class Person1 implements Comparable{
@Override
public String toString() {
return "Person1 [name=" + name + ", age=" + age + "]";
}
public Person1(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person1() {
super();
}
int age;
String name;
@Override
public int compareTo(Object o) {
if(!(o instanceof Person1))
throw new ClassCastException("类型不匹配");
Person1 p=(Person1) o;
//先根据age排序,如果值相等再根据name排序,所以会出现age很小(根据age升序排序)但String字典序很大的对象排在前面的情况
int num=age-p.age;
return num==0? name.compareTo(p.name) :num;//这里调用的是String中的CompareTo方法
}
//这里重写CompareTo方法
}
public class Demo4 {
public static void main(String[] args) {
//TreeSet可以实现不重复(因为compareTo判断相等返回0)有序(根据它返回的正负整数)
//在TreeSet的add方法中调用了元素的的compareTo()方法
//String的compareTo()实现的是字典排序,所以当前的TreeSet可以自动实现字典排序
//CompareTo方法来自Comparable接口
//所以TreeSet要实现有序排重就要实现Comparable接口的CompareTo()方法
TreeSet set=new TreeSet<>();
set.add("java");
set.add("php");
set.add("php");
set.add("python");
set.add("html");
set.add("BigData");
System.out.println(set);
TreeSet set1=new TreeSet<>();
set1.add(new Person1("bingbing",10));
set1.add(new Person1("bingbing",7));
set1.add(new Person1("bingbing",109));
set1.add(new Person1("bingbing",10));
System.out.println(set1);
}
}
输出:
[BigData, html, java, php, python]
[Person1 [name=bingbing, age=7], Person1 [name=bingbing, age=10], Person1 [name=bingbing, age=109]]
[c]reeSet--通过实现Comparator接口,重写Compare方法实现TreeSet的排重有序
import java.util.*;
//TreeSet的第二种排序去重方法
//使用实现了Comparator接口的compare()方法的比较器对象进行比较
//字符串的compareTo()方法默认为按字典序升序排序,String是被final修饰的,不能被重写
//这里通过比较器实现String的其他的排序需求
//要求按照字符串的长短进行排序
//规则:从短到长排序,长度相同再按照字典顺序排
/*
* 1创建实现了Comparator接口的类,作为比较器类
* 2重写compare方法
* 3创建比较器对象
* 4将比较器对象指定给装着字符串的TreeSet
*
* 总结:一共有两种方式让TreeSet排重,有序
* 第一种:让元素实现Comparable接口--默认排序
* 第二种:让元素实现Comparator接口--人工排序
*
* 注意:人工排序的优先级高于默认排序
*
* 实现Comparator接口的作用:
* 1如果已经重写了Comparable接口的CompareTo()方法,它会让这个方法失效而让自己的比较方法有效,因为它的优先级更高
* 2如果没重写Comparable接口的CompareTo()方法,它可以让TreeSet排重,有序
*/
class ComWithLength implements Comparator{
@Override
public int compare(Object o1, Object o2) {
if(!(o1 instanceof String))//这里比较器作用于什么类型的元素比较什么类型
throw new ClassCastException("类型不匹配");
if(!(o2 instanceof String))//这里比较器作用于什么类型的元素比较什么类型
throw new ClassCastException("类型不匹配");
//向下转型
String s1=(String)o1;
String s2=(String)o2;
int num=s1.length()-s2.length();
return num==0?s1.compareTo(s2):num;
}
}
class ComWithPerson implements Comparator<Person2>//这里指定泛型,自动产生的compare方法的参数也会变成这种类型
{
@Override
public int compare(Person2 o1, Person2 o2) {
int num=o1.age-o2.age;
return num==0?o1.name.compareTo(o2.name):num;
}
}
class Person2 {
@Override
public String toString() {
return "Person1 [name=" + name + ", age=" + age + "]";
}
public Person2(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person2() {
super();
}
int age;
String name;
}
public class Demo5 {
public static void main(String[] args) {
//创建比较器对象
ComWithLength c=new ComWithLength();
//要将比较器指定给TreeSet,TreeSet的构造方法是可以接收比较器对象的
TreeSet set=new TreeSet<>(c);
set.add("java");//字符串的compareTo()方法默认为按字典序升序排序,String是被final修饰的,不能被重写
set.add("php"); //这里通过比较器实现其他的排序需求
set.add("php");
set.add("python");
set.add("html");
set.add("BigData");
System.out.println(set);
ComWithPerson cp=new ComWithPerson();
TreeSet<Person2> set1=new TreeSet<Person2>(cp);
set1.add(new Person2("bingbing",10));
set1.add(new Person2("bingbing",7));
set1.add(new Person2("bingbing",109));
set1.add(new Person2("bingbing",10));
System.out.println(set1);
}
}
[d]泛型
import java.util.*;
/*
* 泛型:通过<数据类型>接受一种数据类型,在编译的时候会使用这种数据类型检测结合中的元素
* 如果元素不是<>中规定的类型,就不允许添加到当前的结合中(编译失败)
*
* 泛型的作用:
* 1使用了泛型不再需要进行容错处理,向下转型--简化了代码
* 2将运行阶段的问题提前到了编译阶段检查,提高了代码的安全性和编程效率
*
* 可以使用泛型的位置:类上,接口上,方法上
*/
public class Demo6 {
public static void main(String[] args) {
//当给定list制定泛型后,里面的元素只能是泛型中只定的类型
ArrayList<String> list=new ArrayList<>();//有的版本这样写会报错
//ArrayList<String> list=new ArrayList<String>();这样写就没事了
list.add("java");
list.add("php");
list.add("html");
list.add("BigData");
//list.add(3);//报错,因为通过制定泛型,已经确定参数的类型是String,所以Integer不行了
System.out.println(list);
//遍历
Iterator<String> it=list.iterator();
//使用泛型前,要进行类型相关的处理
// while(it.hasNext()) {
// Object obj=it.next();
// //容错处理
// if(obj instanceof String)
// {
// String str=(String)obj;
// System.out.println(str.length());
// }
// }
//使用泛型后
while(it.hasNext()) {
String str=it.next();
System.out.println(str.length());
}
}
}