Java--集合(Set:HashSet,TreeSet)

一、Set集合:无索引,不可以重复,无序(存取不一致)

LinkedHashSet:底层是链表实现的,是set集合中唯一一个能保证怎么存怎么取的集合对象

           属于HashSet子集,保证元素唯一

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Random;

public class HashSetMethod {
	public static void main(String[] args) {	
		/*
		 * Set集合:无索引,不可以重复,无序(存取不一致)
		   LinkedHashSet:底层是链表实现的,是set集合中唯一一个能保证怎么存怎么取的集合对象
		       属于HashSet子集,保证元素唯一
		 * */
		initHashSet();
		hashSetOnly();
		demo1();//输出10个1~20之间的随机数
		demo2();//去除list集合中重复元素
	}

	//去除list集合中重复元素
	private static void demo2() {
		System.out.println("=============去除重复============");
		ArrayList list = new ArrayList<>();
		list.add("a");
		list.add("c");
		list.add("a");
		list.add("b");
		list.add("b");
		list.add("a");
		list.add("a");
		list.add("b");
		list.add("c");
		
		//1、创建一个LinkedHashSet集合
		LinkedHashSet hash = new LinkedHashSet<>();
		//2、将List集合中所有元素添加到LinkedHashSet中(去除重复的元素)
		hash.addAll(list);
		//3、将List集合中所有元素删除
		list.clear();
		//4、将HashSet中所有非重复元素添加到List中
		list.addAll(hash);
		System.out.println(list);
	}

	//输出10个1~20之间的随机数
	private static void demo1() {
		System.out.println("=============随机数============");
		//1、有Random类创建随机数对象
		Random r = new Random();
		//2、需要存储10个随机数,且不能重复
		HashSet hash = new HashSet<>();
		//3、如果size小于10可以存储
		while(hash.size() < 10){
			//4、通过Random类中nextInt()获取1~20之间随机数
			hash.add(r.nextInt(20) + 1);
		}
		//5、遍历HashSet
		for(Integer inte:hash){
			System.out.print(inte+" ");
		}
	}

	private static void hashSetOnly() {
		System.out.println("==============元素唯一性==============");
		HashSet hash = new HashSet<>();
		hash.add(new Person("张三",20));
		hash.add(new Person("张三",20));
		hash.add(new Person("李四",22));
		hash.add(new Person("李四",22));
		hash.add(new Person("李四",22));
		for(Person p:hash){
			System.out.println(p);
		}
	}

	private static void initHashSet() {
		HashSet hash = new HashSet<>();
		boolean b1 = hash.add("a");  
		boolean b2 = hash.add("a");     //向Set集合中存储重复元素时返回FALSE
		hash.add("b");
		hash.add("c");
		hash.add("d");
		System.out.println(hash);
		System.out.println(b1);
		System.out.println(b2);
		
		for(String string:hash){       //使用迭代器迭代的,都可以使用增强for循环遍历
			System.out.print(string + " ");
		}
	}
}

Person对象

//实现Comparable接口
public class Person implements Comparable{
	private String name;
	private int age;
	
	public Person(){};
	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 boolean equals(Object obj) {
//		System.out.println("执行该步骤");
//		Person p = (Person)obj;
//		return this.name.equals(p.name) && this.age == p.age;
//	}
//	@Override
//	public int hashCode() {   //重写了hashCode执行了equals方法
//		return 10;          
//	}
	
	/*
	 * HashSet原理
           我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
		   当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
		   如果没有哈希值相同的对象就直接存入集合
		   如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
       2、将自定义类的对象存入HashSet去重复
		   类中必须重写hashCode()和equals()方法
		   hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
		   equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储
	 * */
	
	@Override
	/*
	 * 1、31是一个质数(质数:能被1和本身整除的数)
	 * 2、31这个数既不大也不小
	 * 3、31这个数好算,2^5-1
	 * */
	public int 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) {
		if (this == obj)                  //调用对象和传入对象是同一个对象
			return true;
		if (obj == null)					 //传入的对象为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)     //传入对象的姓名不为null
				return false;
		} else if (!name.equals(other.name))//调用对象的姓名 != 传入对象的姓名
			return false;
		return true;
	}
	@Override
	//实现Comparable接口需要重写compareTo方法
	public int compareTo(Person o) {
		/*
		 * compareTo方法返回 0 集合中不存储重复元素
		 * compareTo方法返回 正数 集合中怎么存怎么取
		 * compareTo方法返回 负数 集合中倒叙存储
		 * */
//		return 0;
		int num = this.age - o.age;
		return num == 0 ? this.name.compareTo(o.name) : num;
	}
}

Java--集合(Set:HashSet,TreeSet)_第1张图片


二、TreeSet集合是用来对元素进行排序的,也可以保证元素唯一

TreeSet原理

1、特点

   TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列

2、使用方式

      (1)自然顺序(Comparable)

 TreeSet类的add()方法中会把存入的对象提升为Comparable类型

 调用对象的compareTo()方法和集合中的对象比较

 根据compareTo()方法返回的结果进行存储

   (2)比较器顺序(Comparator)

 创建TreeSet的时候可以制定 一个Comparator

 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序

 add()方法内部会自动调用Comparator接口中compare()方法排序

 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数

   (3)两种方式的区别

 TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)

 TreeSet如果传入Comparator, 就优先按照Comparator

三、List和Set比较

1、List

     (1)普通for循环, 使用get()逐个获取

     (2)调用iterator()方法得到Iterator, 使用hasNext()和next()方法

     (3)增强for循环, 只要可以使用Iterator的类都可以用

     (4)Vector集合可以使用Enumeration的hasMoreElements()和nextElement()方法

2、Set  

     (1)调用iterator()方法得到Iterator, 使用hasNext()和next()方法

     (2)增强for循环, 只要可以使用Iterator的类都可以用

3、普通for循环,迭代器,增强for循环是否可以在遍历的过程中删除

import java.util.Comparator;
import java.util.HashSet;
import java.util.TreeSet;

import com.cat.hashSet.Person;

public class TreeSetMethod {

	public static void main(String[] args) {
		/*
		 * 一、TreeSet集合是用来对元素进行排序的,也可以保证元素唯一
		 * TreeSet原理
		   1、特点
				TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
		   2、使用方式
				(1)自然顺序(Comparable)
					  TreeSet类的add()方法中会把存入的对象提升为Comparable类型
					  调用对象的compareTo()方法和集合中的对象比较
					  根据compareTo()方法返回的结果进行存储
			    (2)比较器顺序(Comparator)
					  创建TreeSet的时候可以制定 一个Comparator
					  如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
					  add()方法内部会自动调用Comparator接口中compare()方法排序
					  调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
		        (3)两种方式的区别
				      TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
		              TreeSet如果传入Comparator, 就优先按照Comparator
		    二、List和Set比较
		       1、List
				 	(1)普通for循环, 使用get()逐个获取
					(2)调用iterator()方法得到Iterator, 使用hasNext()和next()方法
					(3)增强for循环, 只要可以使用Iterator的类都可以用
					(4)Vector集合可以使用Enumeration的hasMoreElements()和nextElement()方法
			   2、Set
					(1)调用iterator()方法得到Iterator, 使用hasNext()和next()方法
					(2)增强for循环, 只要可以使用Iterator的类都可以用
			   3、普通for循环,迭代器,增强for循环是否可以在遍历的过程中删除
		 * */
		initTree();
		objectTree();
		compareObjLength();//比较长度
	}

	//比较长度
	private static void compareObjLength() {
		System.out.println("==============长度比较==============");
		TreeSet t = new TreeSet<>(new CompareLength());
		t.add("ded");
		t.add("dwecsecv");
		t.add("cec");
		t.add("cedscc");
		t.add("c");
		t.add("ce");
		t.add("dece");
		System.out.println(t);
	}

	private static void objectTree() {
		System.out.println("==============compareTo==============");
		/*
		 * compareTo方法返回 0 集合中不存储重复元素
		 * compareTo方法返回 正数 集合中怎么存怎么取
		 * compareTo方法返回 负数 集合中倒叙存储
		 * */
		TreeSet tree = new TreeSet<>();
		tree.add(new Person("张三",30));
		tree.add(new Person("王五",32));
		tree.add(new Person("张三",30));
		tree.add(new Person("李四",22));
		tree.add(new Person("赵六",42));
		tree.add(new Person("许七",22));
		System.out.println('张' + '0');//根据ASCII码值比较
		System.out.println('王' + '0');
		System.out.println('李' + '0');
		System.out.println('赵' + '0');
		System.out.println('许' + '0');
		for(Person p:tree){
			System.out.println(p);
		}
	}

	private static void initTree() {
		TreeSet t = new TreeSet<>();
		t.add(2);
		t.add(3);
		t.add(1);
		t.add(2);
		t.add(3);
		t.add(3);
		t.add(2);
		System.out.println(t);
	}
}

class CompareLength implements Comparator{
	@Override
	public int compare(String s1, String s2) {
		int num = s1.length() - s2.length();
		return num == 0 ? s1.compareTo(s2) : num;
	}
}



你可能感兴趣的:(JavaSE,集合Set)