set集合

Set是一个接口

Set接口和List接口的区别在哪?

List中一些方法(上图中红色标记),在Set中没有,这些方法都与index(位置/索引/下标)有关。 由于List “有序”列表,第一次添加的元素,index的值为0,第二次添加的元素,index的值为1.......... 但是Set “无序”集合,在无序集合中,不存在“下标/索引”的概念,也就是没有第一个元素、第二元素 之类的说法。

set的特点

  1. 无序的,
  2. 不可以添加重复

Set接口有很多实现类,

如HashSet、TreeSet、LinkedHashSet.....等,其中最常用的就是HashSet

方法:

clear ()

删除集合所有元素

remove()

删除集合元素

add ()

添加元素

clear ()

清除所有

contains()

判断是否包含

isEmpty()

是否为空

remove()

删除元素

size()

元素个数

HashSet<String> s  = new HashSet<String>();//创建对象
		s.add("信阳毛尖出名");
		s.add("南阳");
		s.add("洛阳");
		s.add("安阳");
		s.add("淮阳");
		
		System.out.println(s);//Set是无序的 (没有固定的顺序,打印的顺序和插入的顺序不同,并且是会变的)
		
		s.remove("安阳");
		System.out.println(s);
		System.out.println(s.contains("洛阳"));
		
		//请判断set集合中是否有长度大于4的字符串
		//set的遍历  foreach
		for(String t  :  s){
			if(t.length()>4){
				System.out.println(true);
			}
				
		}

不只是Set可以使用foreach遍历,List、数组这些集合形式都可以使用。

foreach删除陷阱

在遍历Set时,改变了Set集合的结构,就会导致程序报错

要求,将set中的所有包含信阳的元素删除:

代码如下:

	
		HashSet<String> s  = new HashSet<String>();//创建对象
		s.add("信阳毛尖出名");
		s.add("南阳");
	
		s.add("信阳");
		//set的遍历  foreach
		for(String t  :  s){
			if(t.indexOf("信阳")>=0){
			s.remove(t);
			}
			
		}
		System.out.println(s);	
	}

报错是java.util.ConcurrentModificationException,foreach中改变了集合的结构

因为在foreach遍历s时,改变了s的结构

解决:克隆一个新的列表

正确代码

public static void main(String[] args) {
		
		HashSet<String> s  = new HashSet<String>();//创建对象
		s.add("信阳毛尖出名");
		s.add("南阳");
		
		s.add("信阳");
		//1 复制set的方法1:克隆
		HashSet<String> s1  = (HashSet<String>) s.clone();
		HashSet<String> s2  = new HashSet<String>();
		//复制set的方法2:addAll 添加所有
		s2.addAll(s);
		//set的遍历  foreach
		for(String t  :  s1){
			if(t.indexOf("信阳")>=0){
			s.remove(t);
			}
			
		}
		System.out.println(s);	
	}

HashSet的存储机制:

toString equals Object类的hashCode方法:该方法默认返回一个对象的地址(准确来说是地址的变形)

HashSet是一个二维数组/链表的结构,有一个原始的长度为16的数组,该数组的每个元素,都指向一个新 的数组来存放元素。 当Set中放入一个元素s时,会经过以下步骤:

1)获取s的hashCode值

2)将值对16求余,得到的结果就是空间编号

3)该元素,就是要准备放入编号2对应的数组空间中

4)在放入之前,会将s与空间2中的已有元素进行equals比较。如果相等,就认为元素重复,放弃插入;如 果都不相等,那么就把s放入到数组中

重写hashCode方法

String a = new String("123");

String b = new String("123");

但是a与b的hashCode值却相同

看到a与b的内存地址不同,但是hashCode值却相同

Set集合中,存放了两个值相同的字符串。

所以,为了避免这种结果的发生,必须保证两个值相同的字符串,他们的hashCode值也相同。

String为了实现这个目的,重写了hashCode方法,返回值不再跟对象的地址有关,而是跟对象的值有关。

Set拓展

实现HashSet中只有一个学生信息(保证学生姓名和年龄不能重复)

1)保证两个值(姓名/年龄)相同的学生,他们的hashCode值也相同 (重写hashCode方法)

2) 保证两个值(姓名/年龄)相同的学生,他们的equals方法返回true(重写equals方法)

代码如下


public class Student {

	String name;
	int age;
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return name+"-"+age;
	}
	
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return 0;
	}
	
	@Override
	public boolean equals(Object obj) {
		
		Student s = (Student) obj;
		if(this.name.equals(s.name) && this.age==s.age){
			return true;
		}
		return false;
	}
}
public class Test {

	public static void main(String[] args) {
		
		Student s1 = new Student();
		s1.name = "jack";
		s1.age = 18;
		
		Student s2 = new Student();
		s2.name = "jack";
		s2.age = 18;
		
		HashSet<Student> hs = new HashSet<Student>();
		
		hs.add(s1);
		hs.add(s2);
		
		System.out.println(hs);
	}

}

set注重独一无的性质,体系集合用于存储无序(存入和取出的顺序不一定相同)的元素,值不能重复。对象的相等性本质是对象hashCode值(Java是依据对象的内存地址计算的此序号)判断的,如果想要让两个对象失视为相等的,就必须Objiet的hashCode方法和equals方法。

HashSet特点:

排列无序,不可重复

底层使用Hash表实现

内部是HashMap

存取速度快

TreeSet特点:

底层使用二叉树实现

排序存储

内部是TreeMap的SortedSet

排列无序,不可重复

LinkedHashSet 特点:

内部是LinkedHashMap

采用hash表存储,并且双向链表记录插入顺序

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值