Set集合框架

 前言:给大家讲讲Set结合框架

 码字不易,点个关注

 转载请说明!


 思维导图:


目录

1.List和Set的区别

1.两者的特点

2.两者之间的对比

3.取值

2.Set集合的特点

3.Set集合的循环方式

4.HashSet去重复以及原理

1.去重复的原理

2.hashCode()与equals()的相关规定:

3.==与equals的区别

5.TreeSet底层实现和原理

 1.自然排序

2.比较器排序(自定义排序)


1.List和Set的区别

List , Set 都是继承自Collection 接口 

1.两者的特点

List 特点:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重复,可以插入多个null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector

 Set 特点:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set 接口常用实现类是 HashSet、LinkedHashSet 以及 TreeSet

2.两者之间的对比

List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变

Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变

3.取值

List 支持for循环,也就是通过下标来遍历,也可以用迭代器(到这里大家可能会好奇foreach怎么不是,因为foreach本质上也是迭代器)

Set只能用迭代,因为他无序,无法用下标来取得想要的值

2.Set集合的特点

1.无序

2.不可重复

3.Set集合的循环方式

1.foreach遍历

2.迭代器

代码展示:

/**
 * 特点: 1.不可重复 2.无序
 * 
 * @author zjjt
 *
 */
public class Dome1 {

	public static void main(String[] args) {
		Set<Object> set = new HashSet<>();
		set.add("a");
		set.add("b");
		set.add("c");
		set.add("b");

		/**
		 * foreach遍历
		 */
		for (Object h : set) {
			System.out.println(h);
		}

		System.out.println("-------------");

		/**
		 * Iterator(迭代器)
		 */
		Iterator<Object> it = set.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}
}

输出结果如下:

 

4.HashSet去重复以及原理

1.去重复的原理

向HashSet 中add ()元素时,判断元素是否存在的依据,不仅要比较hash值,同时还要结合equles 方法比较

*HashSet 中的add ()方法会使用HashMap 的put()方法

Hashset底层数据结构:Hash表

优先会调用hashcade()方法对比地址,然后调用equals()方法对比值

Set集合加的是地址,不允许添加重复的地址

Set集合去重其实是去重一个相同的地址

2.hashCode()与equals()的相关规定:

1.如果两个对象相等,则hashcode一定也是相同的
2.两个对象相等,对两个equals方法返回true
3.两个对象有相同的hashcode值,它们也不一定是相等的
4.综上,equals方法被覆盖过,则hashCode方法也必须被覆盖
5.hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

3.==与equals的区别

1.==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同

2.==是指对内存地址进行比较 equals()是对字符串的内容进行比较3.==指引用是否相同 equals()指的是值是否相同


代码展示:

public class Dome2 {

	public static void main(String[] args) {
      Set<Object> set=new HashSet<>();
      set.add(new people("张三", 20));
      set.add(new people("李四", 22));
      set.add(new people("王五", 24));
      set.add(new people("赵六", 26));
      set.add(new people("李四", 22));
      
      for (Object h : set) {
		System.out.println(h);
	}
	}
}

class people {

	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;
	}

	@Override
	public String toString() {
		return "people [name=" + name + ", age=" + age + "]";
	}

	public people(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

}

输出结果如下:

地址的一个生成规则:

1.new一个对象生成一个新的地址

怎么去实现去重? 

只要去重同一个地址即可,在people类调用hashcade() and equals()方法

Hashset底层数据结构:Hash表

优先会调用hashcade()方法对比地址,然后调用equals()方法对比值

代码展示:

/**
 * Set集合去重
 * Hashset底层数据结构:Hash表
 * 优先会调用hashcade()方法对比地址,然后调用equals()方法对比值
 *
 */
public class Dome2 {

	public static void main(String[] args) {
      Set<Object> set=new HashSet<>();
      set.add(new people("张三", 20));
      set.add(new people("李四", 22));
      set.add(new people("王五", 24));
      set.add(new people("赵六", 26));
      set.add(new people("李四", 22));
      
      for (Object h : set) {
		System.out.println(h);
	}
	}
}

class people {

	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;
	}

	@Override
	public String toString() {
		return "people [name=" + name + ", age=" + age + "]";
	}

	public people(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public int hashCode() {
		System.out.println("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) {
		System.out.println("equals方法被调用");
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		people other = (people) 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;
	}
	
	

}

输出结果如下:

5.TreeSet底层实现和原理

本人使用的是jdk1.8版本

TreeSet实现了SortedSet接口,它是一个有序的集合类,TreeSet的底层是通过TreeMap实现的。TreeSet并不是根据插入的顺序来排序,而是根据实际的值的大小来排序。TreeSet也支持两种排序方式:

  • 自然排序
  • 比较器排序(自定义排序)

  • 排序的意义在哪里?

 假如你和第三方进行一个数据的交互的时候,对方没有做排序

 我们用这个排序(自然排序,自定义排序)去自动排序,脱离数据脚本(sql语句)进行排序

 1.自然排序

特点:写死了排序规则,每一个模块都按照这个规则走,不灵活

代码展示:

/**
 * 自然排序
 * @author zjjt
 *
 */
public class Dome3 {

	public static void main(String[] args) {
		Set<User> set=new TreeSet<>();
		set.add(new User("张三", 20000));
		set.add(new User("李四", 13000));
		set.add(new User("王五", 12500));
		set.add(new User("赵六", 18000));
		
		for (User h : set) {
			System.out.println(h);
		}
	} 
	
}
class User{
	 private String name;
	 private int money;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getMoney() {
		return money;
	}
	public void setMoney(int money) {
		this.money = money;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", money=" + money + "]";
	}
	public User(String name, int money) {
		super();
		this.name = name;
		this.money = money;
	}
	 
	 
}

这里执行会报错的!!!

原因:因为User类没有实现自然排序接口

解决方法:实现自然排序接口并重写方法

/**
 * 自然排序
 * 不方便
 * 把自然排序的接口绑定在了User对象上意味着没办法去做更改
 *
 */
public class Dome3 {

	public static void main(String[] args) {
		Set<User> set=new TreeSet<>();
		set.add(new User("张三", 20000));
		set.add(new User("李四", 13000));
		set.add(new User("王五", 12500));
		set.add(new User("赵六", 18000));
		//com.hpw_set.User cannot be cast to java.lang.Comparable 类型转换异常
		for (User h : set) {
			System.out.println(h);
		}
	} 
	
}
class User implements Comparable{//实现了自然排序接口
	 private String name;
	 private int money;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getMoney() {
		return money;
	}
	public void setMoney(int money) {
		this.money = money;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", money=" + money + "]";
	}
	public User(String name, int money) {
		super();
		this.name = name;
		this.money = money;
	}
	@Override
	public int compareTo(Object o) {
        User u=(User) o;     
		return this.money-u.money; //升序
		//return u.money - this.money;降序
	}
	 
	 
}

输出结果如下(根据money升序输出):

2.比较器排序(自定义排序)

特点:能解决不同的模块有不同的排序规则,你在哪个模块想要哪个排序规则都可以进行定义,修改

代码如下:

/**
 * 比较器排序
 * 能解决不同的模块有不同的排序规则
 * 你在哪个模块想要哪个排序规则都可以进行定义,修改
 *
 */
public class Dome4 {
	public static void main(String[] args) {
		Set<User2> set=new TreeSet<>(new Comparator<User2>() {

			@Override
			public int compare(User2 o1, User2 o2) {
				return -(o1.getMoney()-o2.getMoney());//Money降序
			}
			
		});
		set.add(new User2("张三", 20000));
		set.add(new User2("李四", 13000));
		set.add(new User2("王五", 12500));
		set.add(new User2("赵六", 18000));
		for (User2 h : set) {
			System.out.println(h);
		}
	} 
	
}

class User2 {
	 private String name;
	 private int money;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getMoney() {
		return money;
	}
	public void setMoney(int money) {
		this.money = money;
	}
	@Override
	public String toString() {
		return "User2 [name=" + name + ", money=" + money + "]";
	}
	public User2(String name, int money) {
		super();
		this.name = name;
		this.money = money;
	}
	
	 
	 
}

输出结果如下 (根据money降序输出):

到这里就结束了,我依旧是那个学IT的小学生 

欢迎大佬指点 

猜你喜欢

转载自blog.csdn.net/weixin_56069070/article/details/119044223