set学习笔记
Posted _图南
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了set学习笔记相关的知识,希望对你有一定的参考价值。
1 Set的介绍
set: 存储无序,不可重复的数据
-
- Set接口是Collection的子接口,set接口没有提供额外的方法
- Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set 集合中,则添加操作失败。
- Set 判断两个对象是否相同不是使用
==
运算符,而是根据equals()
方
2 对与无序和不可重复的理解:
无序性:存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的。但是不等于随机性。
不可重复性:保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个(TreeSet除外)。
TreeSet是根据compareTo是否为0进行比较
3 Set接口实现类的对比
---Collection接口:
----set接口:存储无序,不可重复的数据
----HashSet:Set的主要实现类;线程不安全但是效率高;可以储存null值
----LinkedHashSet:是HashSet的子类。可以按照添加的顺序遍历
底层有前后指针,故对于频繁的遍历操作,LinkedHashSet效率是高于 HashSet的
----TreeSet: 可以按照添加对象的指定属性(也就是说,属性的类型要相同),进行操作。
底层是红黑树和HashMap一样
4 HashSet的特点:
不能保证元素的排列顺序
HashSet不是线程安全的
集合元素可以是null
底层也是数组,初始容量为16,当如果使用率超过0.75,(16*0.75=12)就会扩大容量为原来的2倍。(16扩容为32,依次为64,128…等)
HashSet 集合判断两个元素相等的标准:两个对象通过hashCode() 方法比较相等,并且两个对象的equals()方法返回值也相等。
5 添加元素过程
我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,
* 此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断
* 数组此位置上是否已经有元素:
* 如果此位置上没有其他元素,则元素a添加成功。 --->情况1
* 如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
* 如果hash值不相同,则元素a添加成功。--->情况2
* 如果hash值相同,进而需要调用元素a所在类的equals()方法:
* equals()返回true,元素a添加失败
* equals()返回false,则元素a添加成功。--->情况2
*
* 对于添加成功的情况2和情况3而言:元素a 与已经存在指定索引位置上数据以链表的方式存储。
* jdk 7 :元素a放到数组中,指向原来的元素。
* jdk 8 :原来的元素在数组中,指向元素a
* 总结:七上八下
6 HashCode()和equals()的重写
为什么要重写HashCode和equals方法
由于在创建对象时,Object类会随机生成一个哈希值。所以,即使对象的属性元素相同,在HashSet输出时,仍然输出两个对象,不符合不可重复性。故要重写HashCode和equals方法。
具体操作idea有自动重写
7 LinkedHashSet
LinkedHashSet 是 HashSet 的子类
LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置, 但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入 顺序保存的。
LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全 部元素时有很好的性能。
LinkedHashSet 不允许集合元素重复。
内部原理图:
7 TreeSet
TreeSet
底层使用红黑树结构存储数据TreeSet
可以确保集合元素处于排序状态。TreeSet
两种排序方法:自然排序和定制排序。默认情况下,TreeSet
采用自然排序。定制排序是,在创建TreeSet的构造器是含参,并且使用Comparator方法。- 如果试图把一个对象添加到TreeSet时,则该对象的类必须实现Comparable 接口。
- 自然排序:
TreeSet
会调用集合元素的compareTo(Object obj)
方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列。 - 对于
TreeSet
集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过compareTo(Object obj)
方法比较返回值。
Redis学习笔记-Set
package cn.com; import java.util.HashMap; import java.util.Map; import java.util.Set; import redis.clients.jedis.Jedis; /** * 集合的所有操作方法 * * */ public class Redis_Set { public static Jedis redis = new Jedis("localhost", 6379);// 连接redis public static void zadd(){ Map<String,Double> map=new HashMap<String,Double>(); redis.zadd("user",map); } /** * 将一个或多个 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。 * */ public static void sadd(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","d","e","f"); Set<String> setList=redis.smembers("user"); for(String s:setList){ System.out.println(s); } } /** * SCARD key * 返回集合 key 的基数(集合中元素的数量) * */ public static void scard(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","d","e","f"); Long number=redis.scard("user"); System.out.println(number); } /** * SDIFF key [key ...] 求差集 * 返回一个集合的全部成员,该集合是所有给定集合之间的差集。 * 不存在的 key 被视为空集。 * 相当月user减去user1 剩下的 user 元素 * */ public static void sdiff(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","z"); redis.sadd("user1", "a","c","d","f"); Set<String> setList=redis.sdiff("user","user1"); for(String s:setList){ System.out.println(s); } } /** * SDIFFSTORE destination key [key ...]求差集 将结果放入新的结合中 * 这个命令的作用和 SDIFF 类似,但它将结果保存到 destination 集合,而不是简单地返回结果集。 * 如果 destination 集合已经存在,则将其覆盖。 * destination 可以是 key 本身。 * N 是所有给定集合的成员数量之和. * 例如:以下例子是 取出 user中在user1 不包含的元素 也就是(zzz)在user1 中不存在 * */ public static void sdiffstore(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","zzzz"); redis.sadd("user1", "a","b","c","d","e","f"); long size=redis.sdiffstore("newuser","user","user1"); System.out.println("size:"+size); Set<String> setList=redis.smembers("newuser"); for(String s:setList){ System.out.println(s); } } /** * SINTER key [key ...] 求交集 * 返回一个集合的全部成员,该集合是所有给定集合的交集。 * 不存在的 key 被视为空集。 * 当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。 * */ public static void sinter(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","zzzz"); redis.sadd("user1", "a","b","c","d","e","f"); Set<String> setList=redis.sinter("user","user1"); for(String s:setList){ System.out.println(s); } } /** * SINTER key [key ...] 求交集 跟sinter区别在于是将差集的结果集放入新的数组中 如下的:newuser * 返回一个集合的全部成员,该集合是所有给定集合的交集。 * 不存在的 key 被视为空集。 * 当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。 * */ public static void sinterstore(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","zzzz"); redis.sadd("user1", "a","b","c","d","e","f"); long size=redis.sinterstore("newuser","user","user1"); System.out.println("交集的大小:"+size); Set<String> setList=redis.smembers("newuser"); for(String s:setList){ System.out.println(s); } } /** * SUNION key [key ...] * 返回一个集合的全部成员,该集合是所有给定集合的并集。 * 不存在的 key 被视为空集。 * */ public static void sunion(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","zzzz"); redis.sadd("user1", "a","b","c","d","e","f"); Set<String> setList=redis.sunion("user","user1"); for(String s:setList){ System.out.println(s); } } /** * SUNION key [key ...] 将两个集合的并集放入新的结合中 newuser * 返回一个集合的全部成员,该集合是所有给定集合的并集。 * 不存在的 key 被视为空集。 * */ public static void sunionstore(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","zzzz"); redis.sadd("user1", "a","b","c","d","e","f"); long l=redis.sunionstore("newuser","user","user1"); Set<String> setList=redis.smembers("newuser"); for(String s:setList){ System.out.println(s); } } /** * SISMEMBER key member *判断 member 元素是否集合 key 的成员。 * */ public static void sismember(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","zzzz"); boolean b=redis.sismember("user", "a"); boolean b1=redis.sismember("user", "不存在哦"); System.out.println("返回一个 true 跟 false"); System.out.println(b); System.out.println(b1); } /** * 获取集合对象 * */ public static void smembers(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","d","e","f"); Set<String> setList=redis.smembers("user"); for(String s:setList){ System.out.println(s); } } /** * SMOVE source destination member * SMOVE 是原子性操作。 * @param srckey 源集合key * @param dstkey 目标集合key * @param member 要移动的元素 * 将源集合中的 元素member 移动到目标集合中 * 返回值: * 如果 member 元素被成功移除,返回 1 。 * 如果 member 元素不是 source 集合的成员,并且没有任何操作对 destination 集合执行,那么返回 0 。 */ public static void smove(){ redis.flushDB();//清除数据 redis.sadd("user", "a","b","c","zzzz"); redis.sadd("user1", "d","e","f"); redis.smove("user", "user1", "zzzz"); System.out.println("======user剩下的元素应该是 a,b,c======"); Set<String> setList=redis.smembers("user"); for(String s:setList){ System.out.println(s); } System.out.println("======user 1的元素应该是 d,e,f,zzz======"); Set<String> setList1=redis.smembers("user1"); for(String s:setList1){ System.out.println(s); } } /** * SPOP key * 移除并返回集合中的一个随机元素。 * 如果只想获取一个随机元素,但不想该元素从集合中被移除的话,可以使用 SRANDMEMBER 命令。 * */ public static void spop(){ redis.flushDB();//清除数据 redis.sadd("user", "1","2","3","4","5","6","7"); String s=redis.spop("user"); System.out.println("随机弹出并移除的元素:"+s); Set<String> setList=redis.smembers("user"); for(String str:setList){ System.out.println(str); } } /** * 如果命令执行时,只提供了 key 参数,那么返回集合中的一个随机元素。 * */ public static void srandmember(){ redis.flushDB();//清除数据 redis.sadd("user", "1","2","3","4","5","6","7"); String s=redis.srandmember("user"); System.out.println("随机弹出不删除的元素:"+s); Set<String> setList=redis.smembers("user"); for(String str:setList){ System.out.println(str); } } /** * SREM key member [member ...] * 移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略。 * 当 key 不是集合类型,返回一个错误。 * */ public static void srem(){ redis.flushDB();//清除数据 redis.sadd("user", "1","2","3","4","5","6","7"); redis.srem("user", "1","3","5");//删除1,3,5 Set<String> setList=redis.smembers("user"); for(String str:setList){ System.out.println(str); } } public static void main(String [] args){ sunionstore(); } }
以上是关于set学习笔记的主要内容,如果未能解决你的问题,请参考以下文章