HashSet,TreeSet,泛型

[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());
		}
		
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值