Set概述、哈希值概述、HashSet概述(附加存储学生对象案例)、LinkedHashSet概述、TreeSet概述、Comparable和Comparator(附存储不重复随机数案例)

Set集合概述特点

所在包:java.util
public interface Set<E> 
	   extends Collection<E>            
//Set作为接口不能直接进行实例化,必须找到Set相应的实现类。
特点:不包含重复元素的集合
  Set集合中没有带索引的方法,所以不能使用普通for循环遍历

注意:
数组用Arrays类方法
集合用Collections类方法

实现代码案例:

Set<String> s = new HashSet<String>();
	s.add("hello");
	s.add("world");
	s.add("java");
	for(String c:s){
   
		System.out.print(c);        //Set对集合的迭代顺序不做任何保证
	}
输出结果:
world
java
hello

哈希值概述特点

哈希值:

  • 是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
  • Object类中有hashCode()可以获取对象的哈希值:public Object hashCode()返回对象的哈希值

对象的哈希值特点:

  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
  • 默认情况下(没有在类中重写hashCode()方法的情况下),不同对象的哈希值是不同的,重写hashCode()方法可以让不同对象的哈希值相同

HashSet< E >

所在包:java.util
public class HashSet<E> 
	   extends AbstractSet<E> 
       implements Set<E>,Cloneable,Serializable

特点:

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不做任何保证,也就是说不保证存储数据和取出数据的元素顺序一致
  • 没有带索引的方法,所以不能用普通for循环遍历
  • 由于是Set集合,所以在集合中不包含重复的元素

初始化格式:

HashSet<E> hs=new HashSet<E>();
注意:HashSet继承了Set接口所以可以用add、remove、clear、isEmpty、iterator(获取迭代器)等方法

HashSet是如何保证元素不相同的:

  1. 存入的元素和已经存入的元素比较哈希值
  2. 如果哈希值不同,则继续向下执行,把元素添加到集合
  3. 如果哈希值相同,则调用对象的equals方法进一步比较元素值是否相同
  4. 如果equals返回false,则会继续向下执行,把元素添加到集合
  5. 如果equals返回true,则说明元素重复,不会向下执行

图例:

存储学生对象案例:

public static void main(String[] args){
   
	HashSet<Student> h = new HashSet<Student>();
	Student s1=new Student("张三",123,99);
	Student s2=new Student("李四",456,98);
	Student s3=new Student("王五",789,70);
	Student s4=new Student("张三",123,99);
	h.add(s1);
	h.add(s2);
	h.add(s3);
	h.add(s4);
	for(Students:h){
   
		System.out.println(s.getName()+","+s.getId()+","+s.getScore());
	}
}
-------------------------------------------------------------------------------------------------
输出结果:          // 如果在学生类中重写了方法equals()和hashCode()则不会出现重复对象类型
张三,123,99
李四,456,98
张三,123,99
王五,789,70
注意:继承Set接口下的HashSet输出结果不能保证输入和输出的顺序相同

LinkedHashSet< E >

所在包:java.util
public class LinkedHashSet<E> 
	   extends HashSet<E> 
       implements Set<E>,Cloneable,Serializable

LinkedHashSet特点:

  • 底层逻辑由哈希表和链表实现的Set接口,具有可预测的迭代次序(存储顺序和输出顺序相同)
  • 由链表保证元素的有序性,也就是说元素的存储和取出顺序是一致的
  • 由哈希表保证元素的唯一性,也就是说表中没有重复的元素

代码示例:

LinkedHashSet<String> link = new LinkedHashSet<String>();
	link.add("world");
	link.add("hello");
	link.add("java");
	for(String s:link){
   
		System.out.print(s);
	}
输出结果:
World
Hello
java

TreeSet

所在包:java.util
public class TreeSet<E> 
	   extends AbstractSet<E> 
       implements NavigableSet<E>,Cloneable,Serializable

TreeSet集合特点:

  • 元素有序,这里的排序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方法取决于
构造方法名 作用
TreeSet() 根据其元素的自然排序进行排序(例:Integer数字按照从小到大的排序顺序)
TreeSet(Comparator comparator) 根据指定的比较器进行指定的排序

代码实例:

Public static void main(String[] args){
   
	TreeSet<Integer> tree = new TreeSet<Integer>();       
	//注意集合体只能存储引用类型,如int的包装类类型Integer。
	tree.add(9);
	tree.add(8);
	tree.add(7);
	for(Integeri:tree){
   
		System.out.print(i);
	}
}
输出结果:
9
8
7

自然排序Comparable的使用范例

案例要求:存储学生对象并遍历,创建TreeSet集合使用无参构造方法。按照年龄从小到大排序,年龄相同时,按照姓名字母顺序排序
代码实现:

Student类中必须要实现Comparable<E>接口并在类中重写compareTo()方法
public class Student implements Comparable<Student>{
             
//定义学生类 并实现Comparable接口(自然排序接口)
	… …

	@Override              //重写compareTo方法
	public int compareTo(Student s){
   
		int nums = this.Id-s.Id;      
		//在add方法中调用S2.compareTo(S1); 所以this.Id是指S2中的Id,而s.Id则是S1中的Id
		//这是一个主要判断排序条件--按照id大小排序
		int temp = nums == 0 ? this.Name.compareTo(s.Name) : nums;//nums==0则说明年龄相同,比较姓名 
		 //若姓名相同则返回nums给temp
		//这是一个次要判断排序条件--按照姓名顺序排序
		return temp;
	}
}         
public class static void main(String[] args){
   
	TreeSet<Student> t = new TreeSet<Student>();
	Student s1=new Student("zs",4,99);
	Student s2=new Student("ls",3,98);
	Student s3=new Student("ww",1,99);
	Student s4=new Student("lw",2,97);
	Student s5=new Student("ll",2,99);
	t.add(s1);                                         
	t.add(s2);                                                           
	t.add(s3);
	t.add(s4);
	t.add(s5);
	for(Students:t){
   
		System.out.println(s.getName()+","+s.getId()+","+s.getScore());
	}
}
输出结果:
ww,1,99
ll,2,99
lw,2,97
ls,3,98
zs,4,99
-------------------------------------------------------------------------------------------------
小结:
	用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的,自然排序
	就是让接口所属的类实现Comparable<E>接口,重写compareTo(T o)方法,重写方法时,一定
	要注意排序规则必须按照要求的主要条件和次要条件来写。

Comparator的使用范例

案例要求:存储学生对象并遍历,创建TreeSet集合使用带参构造方法。要求按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
代码实现:

public class Student{
   … …}     //用Comparator比较器时可以不用在元素所属的类中实现Comparable接口
Public class static void main(String[] agrs){
   
	TreeSet<Student> t = new TreeSet<Student>(new Comparator<Student>(){
          
	 //利用匿名内部类方法创建Comparator<E>比较器作为TreeSet<E>(Comparator comparator)的参数
		@override
		public int compare(Student s1,Student s2){
       //注意是重写compare方法不是compareTo
			int nums = s1.getId() - s2.getId();                       
			//这是一个主要判断排序条件--按照id大小排序
			int temp = nums == 0 ? s1.getName().compareTo(s2.getName()) : nums;
			//这是一个次要判断排序条件--按照姓名顺序排序
			return temp;
		}
	})
	… …           //与自然排序Comparable代码相同
}
-------------------------------------------------------------------------------------------------
小结:
	用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的比较器排
	序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法,重写
	方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

不重复随机数案例

要求:编写一个程序,获得10个1-20之间的随机数,要求随机数不能重复,并在控制台输出
代码实现:

public static void main(String[]args){
   
	Set<Integer> t = new TreeSet<Integer>();   
	//利用TreeSet给集合Set进行实例化,可让集合中的Integer元素实现自动从小到大排序
	Random r = new Random();          //定义随机数类
	while(t.size() < 10){
   
		int number=r.nextInt(20)+1;
		t.add(number);
	}
	for(Integer i : t){
   
		System.out.print(I + " ");
	}
}
注意:Set集合是接口不能直接进行实例化,可以用TreeSetLinkedHashSetHashSet等类进行实例化。
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务