黑马程序员-集合03

----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------

1.Set接口
Set派系
 *   元素是无序(存储的顺序和取出的)排列
 *   这个派系没有下标
 *   元素不重复(依据是对象的hashCodeequals方法决定的)
 *   Set集合,都是线程不安全的
  
 *   存储到Set集合中的对象,应该重写hashCodeequals方法
  
 *   什么时候需要使用Set集合
 *   当你存储的元素,不能重复的时候,考虑使用Set集合
 
Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一种,迭代器。
	|--HashSet:底层数据结构是哈希表,桶状结构(笼屉)线程是不同步的。无序,高效;
		HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。
		当元素的hashCode值相同时,才继续判断元素的equals是否为true		如果为true,那么视为相同元素,不存。如果为false,那么存储。
		如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。
        |--LinkedHashSet:有序,hashset的子类。
	|--TreeSet:对Set集合中的元素的进行指定顺序的排序。不同步。TreeSet底层的数据结构就是二叉树。
2. HashSet集合
  |-- 底层结构是哈希表,桶状结构
  |-- HashSet调用的是HashMap来实现的
  |-- 线程不安全的,操作效率高
哈希表的原理:
1,对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值。
2,哈希值就是这个元素的位置。
3,如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础 +1顺延。
4,存储哈希值的结构,我们称为哈希表。
5,既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。
	这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。
 
   对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。
对于HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。
|-- 重写equals方法的实现步骤
    1. 对本对象和彼对象(this obj)进行地址的判断,如果地址一样,直接返回true
    2. 对象obj这个参数进行类型的判断,再次进行类型的强制转换
    3. 使用this和被转后的obj,进行所有成员变量的比较
    4. 如果传递的obj参数,不是本类类型直接返回false
 
|-- 重写hashCode方法的实现步骤
将对象中的引用变量取哈希值,基本数据类型直接相加或者相乘
public int hashCode(){
                //zhangsan,20  = 100+20*2 =40 = 140
                //lisi 22      = 98 + 22*2 =44 = 142
                //age*数,降低姓名年龄不一致的时候,而哈希值恰巧一致的概率
		final int X = 3;
		return this.name.hashCode()+age * X ;
	}
	public boolean equals(Object obj){
		if (this == obj)
			return true;
		if( obj instanceof Person){
			Person p = (Person)obj;
			return this.name.equals(p.name) && this.age == p.age ;
		}
		return false;
	}

 3. TreeSet二叉树TreeSet具有排序功能的一个集合    * 底层数据结果是二叉树    * 排序的依据是对象的自然顺序  保证元素唯一性的依据: compareTo方法return 0.(return 1 原顺序 -1倒序)  一个对象是否具有自然顺序,看描述对象的这个类,是否实现了Comparable接口,覆盖接口中的抽象方法 public int compareTo(){}    * 字符串本身具备自然顺序,是因为String类实现了Comparable接口,覆盖了compareTo方法      TreeSet集合排序有两种方式,Comparable和Comparator区别:1:让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法。2 让集合自身具备比较性,自定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数。TreeSet ts  = new TreeSet(new MyCompara());    第二种方式较为灵活。 第一种 实现Comparable接口
public class Person implements Comparable{
       //compareTo方法,建立Person类的比较性的
       //既然有比较,就是两个对象才能比较
       // this 和 o比
	public  int compareTo(Object o){
       //比较对象中的姓名和年龄
       //name姓名是主要的条件,如果this.name 和o.name比较后,如果不是0
       //此时,没有比较比较年龄了,当姓名的比较结果是0的时候,比较年龄
		Person p = (Person)o;
                //this中的name和 p中的name怎么比较,结果才是int类型
		int num = this.name.compareTo(p.name);
		return num==0?this.age -p.age:num;  //三元运算
	}
}

 
第二种 自定义比较器:
自定义比较器,让TreeSet集合自己进行对象的比较,并排序
 * 比较器设计是一个接口java.util.Comparator,只要你实现接口,覆盖方法就可以了
 * TreeSet使用自定义比较器以后,存储的对象的自然顺序,不在参考
import java.util.*;
TreeSet ts  = new TreeSet(new MyCompara());
class MyCompara implements Comparator{
	public int compare(Object o1, Object o2) {
                //强制类型转换
		Person p1 = (Person)o1;
		Person p2 = (Person)o2;
                //比较对象中的成员属性,年龄为主要条件
		int num = p1.getAge() - p2.getAge();
		return num == 0 ? p1.getName().compareTo(p2.getName()):num;
	} 
}
//练习
/*
 * TreeSet存储String对象,字符串
 * 按照字符串的字典顺序,进行排序
 * 
 * 按照存储的字符串的长度排序,如果字符串的长度一致,按照字典排序
 * 
 * 自定义比较器
 */
import java.util.*;
public class TreeSetTest {
	public static void main(String[] args) {
		TreeSet ts = new TreeSet(new StringLength());
		ts.add("rgfd");
		ts.add("hgf");
		ts.add("werdf");
 
		Iterator it = ts.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}
 
 
	public int compare(Object o1,Object o2){
		String s1 = (String)o1;
		String s2 = (String)o2;
		int length = s1.length() - s2.length();
		return length == 0 ? s1.compareTo(s2):length;
	}
}
class StringLength implements Comparator{

----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值