集合-Set

四、Set的使用

4.1 主要实现类和方法

  • 主要实现类就是:HashSet
  • 常用方法:Set接口中声明的方法都是Collection接口声明过的。HashSet能使用的就是Collection中定义的方法。
@Test
	public void test1(){
		Set set = new HashSet();
		
		set.add(223);
		set.add(new String("AA"));
		set.add("CC");
		set.add(223);
		set.add(new String("AA"));
		set.add(new Person("Tom",12));
		set.add(new Person("Tom",12));
		set.add(null);
		
		
		for(Object obj : set){
			System.out.println(obj);
		}
		
	}

4.2 Set的特性:无序性、不可重复性

① 无序性:不等同于随机性!元素在底层储存的位置不是像数组一样是依次紧密排列的,而是参考其hashCode值决定的存储位置。理解为无序性

② 不可重复性:根据对象的equals()进行判断。如果返回true,则添加失败。保证了不可重复性。

4.3 向HashSet中添加数据的过程

如何将元素添加到HashSet中的呢?
 *      前提:HashSet底层也是使用数组+链表+(jdk8:红黑树)存储
 *  	① 将元素e1添加到HashSet中,首先调用e1所在类的hashCode(),获取e1对象的哈希值。
 *      ② 此哈希值,经过某种算法以后,获取其在HashSet底层数组中的存放位置。
 *      ③ 如果此位置上,没有其他任何元素,则e1添加成功  --->情况1
 *        如果此位置上,已经存在某个或某几个元素e2,则继续判断。
 *        		④ 比较e1和e2的哈希值,如果两个哈希值不相同。则e1添加成功。   --->情况2
 *        		  比较e1和e2的哈希值,如果两个哈希值相同,则调用e1所在类的equals()方法
 *        				⑤ equals()方法返回false,则e1添加成功。    --->情况3
 *                        equals()方法返回true,则e1添加失败。       
 *     
 *     情况1:将e1直接保存在数组的指定位置
 *     情况2、情况3:此时e1与现有索引位置上的元素,以链表的方式进行保存。
 *     		> jdk7:新的元素e1方法到数组中,指向原有的元素
 *     		> jdk8:已有的元素的末尾指向新的元素e1.
 *          总结:"七上八下"

4.4 向HashSet中添加的元素所在类的要求

 1. 针对于HashSet或者LinkedHashSet来说,如果多个对象需要存储到上述两个Set中时,为了保证不可重复性,
 *   必须要求对象所属的类要重写hashCode()和equals()(重点)
 2. 重写hashCode()和equals()要保证一致性!相等的对象必须具有相等的散列码

4.5 Set的不同实现类的对比

|-----Collection:存储一个一个的数据
 * 		|-----Set:存储无序的、不可重复的数据: 高中的集合
 * 			|-----HashSet:是Set的主要实现类;线程不安全的;可以存储null值
				|-----LinkedHashSet:是HashSet的子类;在添加数据之外,还通过一对指针记录先后添加						的顺序,使得遍历Set元素时,较HashSet效率更高。
			
			|-----TreeSet:可以按照添加的元素的指定的属性的大小进行遍历;底层使用的是红黑树(排序二						叉树的一种)
			

4.6 LinkedHashSet的测试 (了解)

    @Test
	public void test2(){
		Set set = new LinkedHashSet();
		
		set.add(223);
		set.add(new String("AA"));
		set.add("CC");
		set.add(223);
		set.add(new String("AA"));
		set.add(new Person("Tom",12));
		set.add(new Person("Tom",12));
		set.add(null);
		
		for(Object obj : set){
			System.out.println(obj);
		}
		
	}

4.7 TreeSet添加数据的情况 (了解)

//1. TreeSet可以按照添加的元素的指定的属性的大小进行遍历;
//	排序的方式有:自然排序,定制排序
//2. TreeSet底层使用的是红黑树(排序二叉树的一种)
//3. 要求:向TreeSet中添加的元素必须是同一个类型的对象。
//4. 说明:TreeSet中不能存放相同的元素。判断的标准不再是元素所在类的hashCode()和equals()了。而是按照自然
//     排序或定制排序中重写的compareTo()或compare()进行比较。
  • 自然排序
    举例1:
@Test
	public void test1(){
		
		TreeSet set = new TreeSet();
		set.add("CC");
		set.add("MM");
		set.add("GG");
		set.add("TT");
		set.add("JJ");
		set.add("KK");
//		set.add(123);//报ClassCastException
		
		Iterator iterator = set.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
	}
举例2:
@Test
	public void test2(){
		TreeSet set = new TreeSet();
		
		Person p1 = new Person("Tom",12);
		Person p2 = new Person("Jim",32);
		Person p3 = new Person("Jerry",26);
		Person p4 = new Person("Mike",43);
		Person p5 = new Person("Lily",26);
		
		set.add(p1);
		set.add(p2);
		set.add(p3);
		set.add(p4);
		set.add(p5);
		
		Iterator iterator = set.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
	}

其中,Person类定义如下:

public class Person implements Comparable{
	private String name;
	private int age;
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = 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 "Person [name=" + name + ", age=" + age + "]";
	}
	/*
	@Override
	public int hashCode() { //return age + name.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("Person equals....");
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) 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;
	}
	*/
	//先按照年龄从小到大排列,再按照姓名从小到大排
	@Override
	public int compareTo(Object o) {
			
		if(o instanceof Person){
			Person p = (Person)o;
			int value = this.age - p.age;
			if(value != 0){
				return value;
			}else{
				return this.name.compareTo(p.name);
			}
		}
		
		throw new RuntimeException("输入的类型不匹配");
	}
}
  • 定制排序
@Test
	public void test3(){
		Comparator com = new Comparator(){

			@Override
			public int compare(Object o1, Object o2) {//o1,o2应该为Person的实例
				if(o1 instanceof Person && o2 instanceof Person){
					Person p1 = (Person)o1;
					Person p2 = (Person)o2;
					return -p1.getName().compareTo(p2.getName());
				}
				
				return 0;
			}
			
		};
		TreeSet set = new TreeSet(com);
		
		Person p1 = new Person("Tom",12);
		Person p2 = new Person("Jim",32);
		Person p3 = new Person("Jerry",26);
		Person p4 = new Person("Mike",43);
		Person p5 = new Person("Lily",26);
		
		set.add(p1);
		set.add(p2);
		set.add(p3);
		set.add(p4);
		set.add(p5);
		
		Iterator iterator = set.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值