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等类进行实例化。
全部评论

相关推荐

头像
10-13 18:10
已编辑
东南大学 C++
。收拾收拾心情下一家吧————————————————10.12更新上面不知道怎么的,每次在手机上编辑都会只有最后一行才会显示。原本不想写凉经的,太伤感情了,但过了一天想了想,凉经的拿起来好好整理,就像象棋一样,你进步最快的时候不是你赢棋的时候,而是在输棋的时候。那废话不多说,就做个复盘吧。一面:1,经典自我介绍2,项目盘问,没啥好说的,感觉问的不是很多3,八股问的比较奇怪,他会深挖性地问一些,比如,我知道MMU,那你知不知道QMMU(记得是这个,总之就是MMU前面加一个字母)4,知不知道slab内存分配器-&gt;这个我清楚5,知不知道排序算法,排序算法一般怎么用6,写一道力扣的,最长回文子串反问:1,工作内容2,工作强度3,关于友商的问题-&gt;后面这个问题问HR去了,和中兴有关,数通这个行业和友商相关的不要提,这个行业和别的行业不同,别的行业干同一行的都是竞争关系,数通这个行业的不同企业的关系比较微妙。特别细节的问题我确实不知道,但一面没挂我。接下来是我被挂的二面,先说说我挂在哪里,技术性问题我应该没啥问题,主要是一些解决问题思路上的回答,一方面是这方面我准备的不多,另一方面是这个面试写的是“专业面试二面”,但是感觉问的问题都是一些主管面/综合面才会问的问题,就是不问技术问方法论。我以前形成的思维定式就是专业面会就是会,不会就直说不会,但事实上如果问到方法论性质的问题的话得扯一下皮,不能按照上面这个模式。刚到位置上就看到面试官叹了一口气,有一些不详的预感。我是下午1点45左右面的。1,经典自我介绍2,你是怎么完成这个项目的,分成几个步骤。我大致说了一下。你有没有觉得你的步骤里面缺了一些什么,(这里已经在引导我往他想的那个方向走了),比如你一个人的能力永远是不够的,,,我们平时会有一些组内的会议来沟通我们的所思所想。。。。3,你在项目中遇到的最困难的地方在什么方面4,说一下你知道的TCP/IP协议网络模型中的网络层有关的协议......5,接着4问,你觉得现在的socket有什么样的缺点,有什么样的优化方向?6,中间手撕了一道很简单的快慢指针的问题。大概是在链表的倒数第N个位置插入一个节点。————————————————————————————————————10.13晚更新补充一下一面说的一些奇怪的概念:1,提到了RPC2,提到了fu(第四声)拷贝,我当时说我只知道零拷贝,知道mmap,然后他说mmap是其中的一种方式,然后他问我知不知道DPDK,我说不知道,他说这个是一个高性能的拷贝方式3,MMU这个前面加了一个什么字母我这里没记,别问我了4,后面还提到了LTU,VFIO,孩子真的不会。
走呀走:华子二面可能会有场景题的,是有些开放性的问题了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务