【JAVA学习笔记】17 Set集合

2018.4.19

set

---| Set 接口 无序 不可重复

特有方法: 无

public class Demo1 {
	public static void main(String[] args) {
		Set set = new HashSet();
		
		set.add("1");
		set.add("2");
		set.add("3");
		set.add("4");
		set.add("5");
	//输出无序	
	//	set.add("5");添加不上
		
		System.out.println(set);
		
	}
}
结果:
    [3, 2, 1, 5, 4]

HashSet

---| Set 接口 无序 不可重复

------| HashSet

底层维护的是一个【哈希表--桶式结构(任意元素都可以放)】,存储效率

------| TreeSet

【发现】: 1.添加元素的时候每一次都会调用HashCode方法。 2.重写equals方法和hashCode方法,也是首先调用hashCode方法再来调用equals方法

hashSet存储原理:【背下来】 向hashSet集合中添加元素,hashSet首先会调用该元素的hashCode方法 获取该对象Hash值 通过【移位运算】计算出该元素应该保存在【hash】表中的哪一个位置。

情况1:
	该位置没有任何元素。直接放入。
	
情况2:
	该位置存在其他元素,hash表就会调用该元素的equals方法和已经保存在hash表里面的元素进行比较。
	如果比较结果为TRUE表示相当元素无法添加。如果比较结果为false表示为不同元素可以添加。

哈希表的每一个单元格都是桶式结构,可以保存多个元素,允许元素共存。

class Student {
                	int id;
                	String name;
                	public Student() {}
                	
                	public Student(int id, String name) {
                		this.id = id;
                		this.name = name;
                	}
                	
                	@Override
                	public boolean equals(Object obj) {
                		System.out.println("equals方法");
                		
                		Student student = (Student) obj;
                		System.out.println(this.name+"和"+student.name+"比较!!");
                		
                		return this.name.equals(student.name);
                	}
                	
                	@Override
                	public int hashCode() {//计算获取该元素应该在哈希表中的位置的方法。 是一种移位运算 右移16位经过一系列运算 是唯一值。
                		System.out.println("HashCode方法");
                		return this.id;
                	}
                	
                	@Override
                	public String toString() {
                		// TODO Auto-generated method stub
                		return "[ID:"+ id+" name:"+name+"]";
                	}
                }
                public class Demo2 {
                	public static void main(String[] args) {
                		
                /*
                		HashSet set = new HashSet();
                		
                		set.add("二哥");
                		set.add("伟哥");
                		set.add("光耀");
                		set.add("骚翔");
                		set.add("越南");
                		set.add("子逊");
                		
                		set.add("子逊");
                		
                		System.out.println(set);
                		
                */
                		HashSet set = new HashSet();
                		
                		set.add(new Student(1, "卢子逊"));
                		set.add(new Student(2, "二哥"));
                		set.add(new Student(3, "光耀"));
                		set.add(new Student(4, "魏翔"));
                		set.add(new Student(5, "李伟"));
                		
                		set.add(new Student(5,"G仔"));
                		System.out.println(set);
                	}
                }
                 
  结果:                      
    
    HashCode方法
    HashCode方法
    HashCode方法
    HashCode方法
    HashCode方法
    HashCode方法
    equals方法
    G仔和李伟比较!!
    [[ID:1 name:卢子逊], [ID:2 name:二哥], [ID:3 name:光耀], [ID:4 name:魏翔], [ID:5 name:G仔], [ID:5 name:李伟]]

TreeSet

TreeSet是一个树型结构的set结构。

发现:
	TreeSet中添加元素原本是字符串类型,当添加自定义对象,或者数字的时候,报异常!!
	ClassCastException
	
原因:
	因为TreeSet是一个树型结构,所有的元素都需要进行比较之后才可以放到set集合中,
	而字符串和自定义类对象是没有比较的方式和方法的。
	
	【要求】在TreeSet里面的所有的元素都要有比较的方式或者有【自然顺序】。
	
TreeSet添加自定义元素的方式:
	方式1:
		让这个自定义类【遵从】Comparable接口,是先ComparaTo方法
	方式2:
		自定义比较器,这个表扣机器是【遵从】comparator接口,实现
		int compare(object o1, object o2);
		
		可以在创建TreeSet对象的时候,传入比较器对象作为比较方式。
	
	

    class Person implements Comparable<Person> {
    	
    	int id;
    	String name;
    	int salary;
    	
    	public Person() {}
    	
    	public Person(int id, String name, int salary) {
    		this.id = id;
    		this.name = name;
    		this.salary = salary;
    	}
    /*
    	@Override
    	public int compareTo(Object o) {
    		
    		 返回值有三种: 0 正整数 负整数
    		 0 		表示相同
    		 正整数 	【表示调用这个方法的对象】大于传值的对象
    		 负整数 	【表示调用这个方法的对象】小于传值的对象
    		 
    		
    		//以工资为标准进行判断
    		System.out.println("这里是类内的比较方式");
    		Person person =(Person) o;
    		return this.salary - person.salary;
    	}
    */
    	@Override
    	public String toString() {
    		return "ID:"+id+" name:"+name+" salary:"+ salary+"]";
    	}
    
    @Override
    public int compareTo(Person o) {
    	
    	return this.salary - o.salary;
    }
    
    
    }
    
    class MyCompare implements Comparator {
    	
    	@Override
    	
    	public int compare(Object o1, Object o2) {
    		
    		System.out.println("自定义比较器");
    		Person p1 = (Person) o1;
    		Person p2 = (Person) o2;
    	
    		return p1.salary - p2.salary;
    	}
    }
    
    public class Demo1 {
    	
    	public static void main(String[] args) {
    		//创建TreeSet的时候,传入自定义比较器对象
    		TreeSet set = new TreeSet(new MyCompare());
    		
    		
    		//TreeSet set = new TreeSet();
    
    		//set.add(1);//lang.String cannot be cast to java.lang.Integer
    		
    		set.add(new Person(1,"卢子逊",3000));//com.biteware.treeSet.Person cannot be cast to java.lang.Comparable
    		set.add(new Person(2,"骚逊",3100));
    		set.add(new Person(3,"魏翔",3200));
    		set.add(new Person(4,"李伟",3200));
    		set.add(new Person(5,"光耀",3300));
    		
    		System.out.println(set);
    
    	}
    }
    
结果:
    自定义比较器
    自定义比较器
    自定义比较器
    自定义比较器
    自定义比较器
    自定义比较器
    自定义比较器
    自定义比较器
    [ID:1 name:卢子逊 salary:3000], ID:2 name:骚逊 salary:3100], ID:3 name:魏翔 salary:3200], ID:5 name:光耀 salary:3300]]

总结

ArrayList底层维护的是一个Object类型的数组,使用无参构造方法,创建一个ArrayList集合对象
默认的元素个数为10
特征: 
	查询快,增删慢。
	
	查询快:
		使用的是数组的下标访问方式,可以直达目标位置。
	增删慢:
		增加,有可能会触发数组的扩容机制,会创建一个新的数组元素个数大约是原数组的1.5倍 
		然后会有一个数组拷贝的过程,这个过程是将原数组里面的每一个元素挨个
		复制的新数组中。这个操作消耗大量的时间和空间。
		
		删除,是从object数组中删除一个元素,删除之后,后面元素会向前移动,移动的过程是一个
		复制的过程,这个操作比较浪费时间
		
		增加的原理是:
			newCapacity = oldCapacity + (oldCapacity >> 1);
			
	LinkedList:
		底层维护的是一个链表 (数据结构)
		增删快,查找慢
		
	Vectior 线程安全,效率较低的Arraylist jdk1.0 (不考虑使用)
	
	HashSet
		底层维护的是一个哈希表。存储效率极高
		
		存储原理:
			调用存入对象的hashCode方法,获取到该对象的hashCode的值,通过【移位运算】
			计算该对象应该放到哈希表的那一个位置
			
			情况1:
				该位置没有任何元素,直接添加。
			情况2:
				该位置存在其他元素,这时候会调用对象的equals方法,和在该位置保存的其他元素
				进行一一比较,如果所有的比较结果都为false,表示不相同,可以添加
				如果出现任何一个true,表示和该位置其他的元素相同,不能添加。
				
				
	TreeSet
		存入TreeSet的元素必须有自然顺序或者存在比较方式
		
		自定义类对象,想要放入到TreeSet集合中,有两种方式:
			1.该自定义类【遵从】Comparable接口,实现compareTo(object o)
			2.给TreeSet提供自己定义比较器,创建自定义比较器需要【遵从】
			Comparator接口实现Compare(Object o1,object o2);

猜你喜欢

转载自blog.csdn.net/u013182992/article/details/80453252
今日推荐