黑马程序员------毕老师视频笔记第13-17天------集合Collection-Set-(HashSet、TreeSet)

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

Collection中除了List之外还有一个派系叫做Set

 

Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复

想重复,找List

 

public interface Set extends Collection

 

查阅API发现,Set集合的功能和Collection是一致的

子类,常用,HashSet、TreeSet

 

HashSet:底层数据结构是哈希表

HashSet只有一种取出方法,迭代器Iterator

HashSet线程是非同步的

 

HashSet hs = new HashSet();

hs.add(“111”);//结果为true

hs.add(“111”);//结果为false

 

hashSet是如何保证元素的唯一性的呢?

是通过元素的两个方法,hashCode和equals来完成的

如果元素的hashCode 值相同,才会判断equals是否为true

如果元素的hashCode值不同,不会调用equals

 

哈希表先看哈希值

若是对象是否相同的判定不是哈希值,而是自定义的,需要重载hashCode()

 

注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法

 

hashCode()方法和equals()方法来自于Object类,在Object类中,equals比较的是内存地址,而hashCode返回的也是内存地址,如果两个对象比较的equals值为true,则表示hashCode值也相同。

如果需要自定义比较方式,复写了equals方法,则需要用相应的方式复写hashCode方法,否则是达不到效果的。

 

HashSet存储的时候,会自动调用hashCode和equals,判断要不要往集合中存

HashSet判断一个元素是否存在,以及删除一个元素的时候,也会先调用hashCode和equals来判断。

示例:

import java.util.*;
class Demo
{
	public static void main(String [] args)
	{
		HashSet hs = new HashSet();
		hs.add(new Person("aaa",13));
		hs.add(new Person("bbb",14));
		hs.add(new Person("ccc",15));
		hs.add(new Person("bbb",14));
		hs.add(new Person("aaa",13));

		Iterator it = hs.iterator();
		while (it.hasNext())
		{
			Person p = (Person)it.next();
			System.out.println("name:"+p.name+"---age:"+p.age);
		}
	}
}
class Person
{
	String name;
	int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	public boolean equals(Object obj)
	{
		if (!(obj instanceof Person))
			return false;
		Person p = (Person)obj;
		return this.name==p.name&&this.age==p.age;
	}
	public int hashCode()
	{
		return this.name.hashCode()+age*37;
	}
}


TreeSet:底层数据结构是二叉树,可以对Set集合中的元素进行排序

要保证元素唯一性的依据:compareTo方法,返回0表示相等

 

TreeSet对元素的排序有两种,一种是自然排序,一种是客户化排序。

自然排序:

让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法,这种方式也成为元素的自然顺序,或者叫默认顺序

Java类库中有一些类默认实现了Comparable接口,具有比较性

BigDecimal、BigInteger、Byte、Double、Float、Integer、Long、Short

Character

String

自定义的类想要具有比较性,就要手动的实现Comparable接口,复写compareTo方法。

TreeSet比较两个对象的大小,只看compareTo的值。

注意:排序时,当主要条件相同时,一定要判断一下次要条件。否则视为相同的元素。

Comparable接口,实现该接口可以强制让自定义的类的对象具有比较性

 

TreeSet的第二种排序方式:

当元素自身不具备比较性,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。

定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数

TreeSet有一个构造函数

TreeSet(Comparator<? super E>comparator)

 

比较器:定义一个类实现Comparator接口,覆盖compara方法

 

当两种排序都在时,以比较器为主

 

示例:

import java.util.*;
class Demo
{
	public static void main(String [] args)
	{
		TreeSet ts1 = new TreeSet();
		ts1.add(new Person("rgv",16));
		ts1.add(new Person("hth",23));
		ts1.add(new Person("adfe",12));
		ts1.add(new Person("dfe",12));
		ts1.add(new Person("rgesg",4));

		Iterator it1 = ts1.iterator();
		while (it1.hasNext())
		{
			Person p = (Person)it1.next();
			System.out.println("name:"+p.name+"---age:"+p.age);
		}
		
		TreeSet ts2 = new TreeSet(new MyComparator());
		ts2.add(new Person("rgv",16));
		ts2.add(new Person("hth",23));
		ts2.add(new Person("adfe",12));
		ts2.add(new Person("dfe",12));
		ts2.add(new Person("rgesg",4));

		Iterator it2 = ts2.iterator();
		while (it2.hasNext())
		{
			Person p = (Person)it2.next();
			System.out.println("name:"+p.name+"-------age:"+p.age);
		}
	}
}
//定义一个Person类,实现Comparable接口,让它具有比较性
//比较规则:姓名年龄都相同,视为对象相同
//排序规则:按年龄排序,年龄相同,按姓名字符串排序
class Person implements Comparable
{
	String name;
	int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	public int compareTo(Object o)
	{
		Person p = (Person)o;
		if (this.age>p.age)
			return 1;
		else if (this.age == p.age)
			return this.name.compareTo(p.name);
		else return -1;
	}
}
//定义比较器,按姓名字符串排序
class MyComparator implements Comparator
{
	public int compare(Object obj1,Object obj2)
	{
		Person p1 = (Person)obj1;
		Person p2 = (Person)obj2;
		return p1.name.compareTo(p2.name);
	}
}

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值