集合框架Set

1、集合框架Set(HashSet哈希表存储、重复元素存储底层探究)

HashSet 具有父类Se t接口的特性,底层数据结构是哈希表
(一).HashSet哈希表存储
一、元素是无序(存入和取出的顺序不一定一致)

package com.qukang.set;

import java.util.HashSet;

public class SetDemo {
public static void main(String[] args) {
	HashSet hs=new HashSet<>();
	hs.add("zs");
	hs.add("ls");
	hs.add("ww");
	hs.add("mazi");
	for (Object obj : hs) {
		System.out.println(obj);
	}
}
}
  • 输出结果
    在这里插入图片描述
  • 并且元素不可以重复;
package com.qukang.set;

import java.util.HashSet;

public class SetDemo {
public static void main(String[] args) {
	HashSet hs=new HashSet<>();
	hs.add("zs");
	hs.add("ls");
	hs.add("ww");
	hs.add("mazi");
	hs.add("zs");
	for (Object obj : hs) {
		System.out.println(obj);
	}
	System.out.println(hs.size());
}
}
  • 输出结果
    在这里插入图片描述
    (二).重复元素存储底层探究
    特点:HashSet 把内存当成了一张表,把空间分成了N份,每次先比较HashCode值,HashCode值就相当于这个张表的ID,如果HashCode值返回的是true,就确定了这个对象摆放的位置,就调用equals方法来比较元素,相比于Arraylist HashSet比Arraylist 多调用了HashCode方法。
    一、 HashSet元素是不可重复的,针对于基本数据类型以及String,引用数据类型去重需要重写hashCode方法以及equals反法
    在这里插入图片描述 a .返回HashCode值一样时每次都要调用equals方法
package com.qukang.set;

import java.util.HashSet; 
public class SetDemo {
public static void main(String[] args) {
	HashSet hs=new HashSet<>();
	hs.add(new Person("zs",12));
	hs.add(new Person("ls",13));
	hs.add(new Person("ww",14));
	hs.add(new Person("mz",15));
	hs.add(new Person("zs",12));
	System.out.println("去重之后的长度:"+hs.size());
}
}
class Person{
	private String uname;
	private int age;
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person(String uname, int age) {
		super();
		this.uname = uname;
		this.age = age;
	}
	public Person() {
		super();
	}
	@Override
	public String toString() {
		return "Person [uname=" + uname + ", age=" + age + "]";
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		System.out.println("来了老弟......"+this.getUname());
		return 60;
	}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(obj instanceof Person) {
			Person p=(Person)obj;
			System.out.println(this.getUname()+"----equals-----"+p.getUname());
			return this.getUname().equals(p.getUname()) && this.getAge()==p.getAge();
		}
		return false;
	}
}

a .返回HashCode值一样时输出结果
在这里插入图片描述
b .返回HashCode值不一样时,只有找到HashCode值一样的时候才调用equlas方法

package com.qukang.set;

import java.util.HashSet;

public class SetDemo {
public static void main(String[] args) {
	HashSet hs=new HashSet<>();
	hs.add(new Person("zs",12));
	hs.add(new Person("ls",13));
	hs.add(new Person("ww",14));
	hs.add(new Person("mz",15));
	hs.add(new Person("zs",12));
	System.out.println("去重之后的长度:"+hs.size());
}
}
class Person{
	private String uname;
	private int age;
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person(String uname, int age) {
		super();
		this.uname = uname;
		this.age = age;
	}
	public Person() {
		super();
	}
	@Override
	public String toString() {
		return "Person [uname=" + uname + ", age=" + age + "]";
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		System.out.println("来了老弟......"+this.getUname());
		return this.getUname().hashCode() + this.age;
		}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(obj instanceof Person) {
			Person p=(Person)obj;
			System.out.println(this.getUname()+"----equals-----"+p.getUname());
			return this.getUname().equals(p.getUname()) && this.getAge()==p.getAge();
		}
		return false;
	}
}

b .返回HashCode值不一样时只有找到HashCode值一样的时候才调用equlas反法的结果
在这里插入图片描述

2、集合框架TreeSet(自然排序、数据结构二叉树、比较器排序)

  • TreeSet自然排序
  • TreeSet可以对set集合中元素进行排序
  • String实现了Comparable接口,所以可以直接进行排序
  • 引用数据类型想要排序,必须实现Comparable接口
  • 其他引用数据类型没有实现Comparable接口,那么会出现java.lang.ClassCastException: com.javaxl.Peroon cannot be cast to java.lang.Comparable,实现引用数据类型实现此接口就没问

1.排序注意:

  • 返回的共享数据是无序的,需要自己进行排序
  • 因为String实现了Comparable接口,所以可以直接进行排序
  • 但是引用数据类型想要排序,必须实现Comparable接口
  • 注意:排序时,当主要条件相同时,一定要判断次要条件
    */
    a.TreeSet String类型排序
package com.qukang.set;

import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetDome {
	public static void main(String[] args) {
		TreeSet ts=new TreeSet<>();
		ts.add("zs");
		ts.add("ls");
		ts.add("ww");
		ts.add("mz");
		ts.add("ed");
		Iterator it = ts.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}

TreeSet String 类型排序结果:
在这里插入图片描述
b.TreeSet 引用累计进行排序有两种方法

  • 1.实现Comparable接口,让元素具有比较性
    缺点:维护性较差,就也是程序的拓展性较差;
package com.qukang.set;

import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDome {
	public static void main(String[] args) {
		TreeSet ts=new TreeSet<>();
		ts.add(new Person("zs",12));
		ts.add(new Person("ls",13));
		ts.add(new Person("ww",14));
		ts.add(new Person("mz",12));
		Iterator it = ts.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}
class Person implements Comparable<Person>{
	private String uname;
	private int age;
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person(String uname, int age) {
		super();
		this.uname = uname;
		this.age = age;
	}
	public Person() {
		super();
	}
	@Override
	public String toString() {
		return "Person [uname=" + uname + ", age=" + age + "]";
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		System.out.println("来了老弟......"+this.getUname());
		return this.getUname().hashCode() + this.age;
		}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(obj instanceof Person) {
			Person p=(Person)obj;
			System.out.println(this.getUname()+"----equals-----"+p.getUname());
			return this.getUname().equals(p.getUname()) && this.getAge()==p.getAge();
		}
		return false;
	}

	@Override
	public int compareTo(Person o) {
		// TODO Auto-generated method stub
		int num=this.getAge() - o.getAge();
		if(num==0) {
		return this.getUname().compareTo(o.getUname());
		}
		return num;
	}
}


CompareTo方法:

  • 本方法用来定义排序的规则
  • 正数:代表后面的比前面的大
  • 0:代表后面和前面一样
  • 负数:代表后面的比前面的小
  • this.:代表还没有存放在容器中的对象
  • o:代表已经在容器的对象
    注意:排序时,当主要条件相同时,一定要判断次要条件
	@Override
	public int compareTo(Person o) {
		// TODO Auto-generated method stub
		int num=this.getAge() - o.getAge();
		if(num==0) {
		return this.getUname().compareTo(o.getUname());
		}
		return num;
	}
  • 实现Comparable接口结果:
    在这里插入图片描述
  • 2.实现Comparator接口,让容器具有比较性
    针对于需求而发生改变
package com.qukang.set;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDome {
	public static void main(String[] args) {
		TreeSet ts=new TreeSet<>(new PersonComp());
		ts.add(new Person("zs",12));
		ts.add(new Person("ls",13));
		ts.add(new Person("ww",14));
		ts.add(new Person("mz",12));
		Iterator it = ts.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}

class PersonComp implements Comparator<Person>{
	/**
	 * 本方法用来定义排序的规则
	 * 正数:代表后面的比前面的大
	 * 0:代表后面和前面一样
	 * 负数:代表后面的比前面的小
	 * 	o1:代表还没有存放在容器中的对象
	 * 	o2:代表已经在容器的对象
	 */
	@Override
	public int compare(Person o1, Person o2) {
		// TODO Auto-generated method stub
		int num1=o1.getUname().compareTo(o2.getUname());
		if(num1==0) {
		 return	o2.getAge()-o1.getAge();
		}
		return num1;
	}
	
}



Comparator方法:

相对于ComparaTo方法Comparator

  • 本方法用来定义排序的规则
  • 正数:代表后面的比前面的大
  • 0:代表后面和前面一样
  • 负数:代表后面的比前面的小
  • o1:代表还没有存放在容器中的对象
  • o2:代表已经在容器的对象
  • 注意:排序时,当主要条件相同时,一定要判断次要条件
	@Override
	public int compare(Person o1, Person o2) {
		// TODO Auto-generated method stub
		int num1=o1.getUname().compareTo(o2.getUname());
		if(num1==0) {
		 return	o2.getAge()-o1.getAge();
		}
		return num1;
	}
	

实现Comparator接口结果:
在这里插入图片描述
两个接口的区别
当两种排序都存在时,比较器排序优先级更高
因此比较器用的多一些,在实际开发中,很多时候,引用数据类型是否具有比较性,或者比较规则,可能不由开发人员自己决 定,
那么开发人员想要对应的引用数据类型按照自己的排序方式进行排列,那么就需要实现comparator接口,实现compare方法

3、泛型

泛型的好处:
a.将运行的时的错误转换到编译时错误
b.提升了代码的健壮性,简化了代码

  • 运行时报错:
    在这里插入图片描述

  • 编译时报错:
    在这里插入图片描述

  • 如果你不写泛型,就需要写一下代码来代替;

package com.qukang.set;

import java.util.HashSet;
import java.util.Iterator;

public class HashSetDemo {
	public static void main(String[] args) {
		HashSet hs=new HashSet<>();
		hs.add(22);
		hs.add(32);
		hs.add(34);
		hs.add(454);
		hs.add(88);
		hs.add("zs");
		Iterator it = hs.iterator();
		while(it.hasNext()) {
			Object obj=it.next();
			if(obj instanceof Integer) {
				int i=(Integer)obj;
				if(i==0) {
					System.out.println(i);
				}
		}
	}	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值