Java集合框架 HashSet

示例 1 : 元素不能重复

Set中的元素,不能重复

  1. package collection;
  2. import java.util.HashSet;
  3. public class TestCollection {
  4. public static void main(String[] args) {
  5. HashSet<String> names = new HashSet<String>();
  6. names.add("gareen");
  7. System.out.println(names);
  8. //第二次插入同样的数据,是插不进去的,容器中只会保留一个
  9. names.add("gareen");
  10. System.out.println(names);
  11. }
  12. }

示例 2 : 没有顺序

Set中的元素,没有顺序。

严格的说,是没有按照元素的插入顺序排列

HashSet的具体顺序,既不是按照插入顺序,也不是按照hashcode的顺序。

以下是HashSet源代码中的部分注释

  1. /**
  2. * It makes no guarantees as to the iteration order of the set;
  3. * in particular, it does not guarantee that the order will remain constant over time.
  4. */

不保证Set的迭代顺序; 确切的说,在不同条件下,元素的顺序都有可能不一样

换句话说,同样是插入0-9到HashSet中, 在JVM的不同版本中,看到的顺序都是不一样的。 所以在开发的时候,不能依赖于某种臆测的顺序,这个顺序本身是不稳定的

  1. package collection;
  2. import java.util.HashSet;
  3. public class TestCollection {
  4. public static void main(String[] args) {
  5. HashSet<Integer> numbers = new HashSet<Integer>();
  6. numbers.add(9);
  7. numbers.add(5);
  8. numbers.add(1);
  9. // Set中的元素排列,不是按照插入顺序
  10. System.out.println(numbers);
  11. }
  12. }

示例 3 : 遍历

Set不提供get()来获取指定位置的元素

所以遍历需要用到迭代器,或者增强型for循环

  1. package collection;
  2. import java.util.HashSet;
  3. import java.util.Iterator;
  4. public class TestCollection {
  5. public static void main(String[] args) {
  6. HashSet<Integer> numbers = new HashSet<Integer>();
  7. for (int i = 0; i < 20; i++) {
  8. numbers.add(i);
  9. }
  10. //Set不提供get方法来获取指定位置的元素
  11. //numbers.get(0)
  12. //遍历Set可以采用迭代器iterator
  13. for (Iterator<Integer> iterator = numbers.iterator(); iterator.hasNext();) {
  14. Integer i = (Integer) iterator.next();
  15. System.out.println(i);
  16. }
  17. //或者采用增强型for循环
  18. for (Integer i : numbers) {
  19. System.out.println(i);
  20. }
  21. }
  22. }

示例 4 : HashSet和HashMap的关系

通过观察HashSet的源代码,

可以发现HashSet自身并没有独立的实现,而是在里面封装了一个Map.

HashSet是作为Map的key而存在的

而value是一个命名为PRESENT的static的Object对象,因为是一个类属性,所以只会有一个。

  1. private static final Object PRESENT = new Object();
  2. package collection;
  3. import java.util.AbstractSet;
  4. import java.util.HashMap;
  5. import java.util.Iterator;
  6. import java.util.Set;
  7. public class HashSet<E>
  8. extends AbstractSet<E>
  9. implements Set<E>, Cloneable, java.io.Serializable
  10. {
  11. //HashSet里封装了一个HashMap
  12. private HashMap<E,Object> map;
  13. private static final Object PRESENT = new Object();
  14. //HashSet的构造方法初始化这个HashMap
  15. public HashSet() {
  16. map = new HashMap<E,Object>();
  17. }
  18. //向HashSet中增加元素,其实就是把该元素作为key,增加到Map中
  19. //value是PRESENT,静态,final的对象,所有的HashSet都使用这么同一个对象
  20. public boolean add(E e) {
  21. return map.put(e, PRESENT)==null;
  22. }
  23. //HashSet的size就是map的size
  24. public int size() {
  25. return map.size();
  26. }
  27. //清空Set就是清空Map
  28. public void clear() {
  29. map.clear();
  30. }
  31. //迭代Set,就是把Map的键拿出来迭代
  32. public Iterator<E> iterator() {
  33. return map.keySet().iterator();
  34. }
  35. }

练习HashSet

创建一个长度是100的字符串数组

使用长度是2的随机字符填充该字符串数组

统计这个字符串数组里重复的字符串有多少种

使用HashSet来解决这个问题

答案 :

  1. package collection;
  2. import java.util.HashSet;
  3. public class TestCollection {
  4. public static void main(String[] args) {
  5. String[] ss = new String[100];
  6. // 初始化
  7. for (int i = 0; i < ss.length; i++) {
  8. ss[i] = randomString(2);
  9. }
  10. // 打印
  11. for (int i = 0; i < ss.length; i++) {
  12. System.out.print(ss[i] + " ");
  13. if (19 == i % 20)
  14. System.out.println();
  15. }
  16. HashSet<String> result = new HashSet<>();
  17. for (String s1 : ss) {
  18. int repeat = 0;
  19. for (String s2 : ss) {
  20. if (s1.equalsIgnoreCase(s2)) {
  21. repeat++;
  22. if (2 == repeat) {
  23. // 当repeat==2的时候,就找到了一个非己的重复字符串
  24. result.add(s2);
  25. break;
  26. }
  27. }
  28. }
  29. }
  30. System.out.printf("总共有 %d种重复的字符串%n", result.size());
  31. if (result.size() != 0) {
  32. System.out.println("分别是:");
  33. for (String s : result) {
  34. System.out.print(s + " ");
  35. }
  36. }
  37. }
  38. private static String randomString(int length) {
  39. String pool = "";
  40. for (short i = '0'; i <= '9'; i++) {
  41. pool += (char) i;
  42. }
  43. for (short i = 'a'; i <= 'z'; i++) {
  44. pool += (char) i;
  45. }
  46. for (short i = 'A'; i <= 'Z'; i++) {
  47. pool += (char) i;
  48. }
  49. char cs[] = new char[length];
  50. for (int i = 0; i < cs.length; i++) {
  51. int index = (int) (Math.random() * pool.length());
  52. cs[i] = pool.charAt(index);
  53. }
  54. String result = new String(cs);
  55. return result;
  56. }
  57. }

Java自学-集合框架 HashSet的更多相关文章

  1. Java自学-集合框架 HashSet、LinkedHashSet、TreeSet之间的区别

    HashSet. LinkedHashSet.TreeSet之间的区别 步骤 1 : HashSet LinkedHashSet TreeSet HashSet: 无序 LinkedHashSet: ...

  2. Java自学-集合框架 Collections

    Java集合框架 工具类Collections Collections是一个类,容器的工具类,就如同Arrays是数组的工具类 步骤 1 : 反转 reverse 使List中的数据发生翻转 pack ...

  3. Java自学-集合框架 Collection

    Java集合框架 Collection Collection是一个接口 步骤 1 : Collection Collection是 Set List Queue和 Deque的接口 Queue: 先进 ...

  4. Java自学-集合框架 HashMap

    Java集合框架 HashMap 示例 1 : HashMap的键值对 HashMap储存数据的方式是-- 键值对 package collection; import java.util.HashM ...

  5. Java自学-集合框架 二叉树

    Java集合框架 二叉树 示例 1 : 二叉树概念 二叉树由各种节点组成 二叉树特点: 每个节点都可以有左子节点,右子节点 每一个节点都有一个值 package collection; public ...

  6. Java自学-集合框架 LinkedList

    Java集合框架 LinkedList 序列分先进先出FIFO,先进后出FILO FIFO在Java中又叫Queue 队列 FILO在Java中又叫Stack 栈 示例 1 : LinkedList ...

  7. Java自学-集合框架 与数组的区别

    Java集合框架与数组的区别 示例 1 : 使用数组的局限性 如果要存放多个对象,可以使用数组,但是数组有局限性 比如 声明长度是10的数组 不用的数组就浪费了 超过10的个数,又放不下 //Test ...

  8. Java自学-集合框架 ArrayList和HashSet的区别

    Java ArrayList和HashSet的区别 示例 1 : 是否有顺序 ArrayList: 有顺序 HashSet: 无顺序 HashSet的具体顺序,既不是按照插入顺序,也不是按照hashc ...

  9. Java自学-集合框架 遍历

    遍历ArrayList的三种方法 步骤 1 : 用for循环遍历 通过前面的学习,知道了可以用size()和get()分别得到大小,和获取指定位置的元素,结合for循环就可以遍历出ArrayList的 ...

随机推荐

  1. 创建Npm脚手架

    1工具 l  Npm ( https://nodejs.org/en/ ) l  Yeoman (npm install -g yo) l  generator-generator (npm inst ...

  2. gitlab设置项目组成员权限

    你敢相信这是个码农? setting菜单的“Members”功能页: 该页面展示了当前Project的成员列表,以及每个成员对应的权限角色,Owner/Master/Developer 注意到该页面顶 ...

  3. 使用maven-compiler-plugin以及maven-shade-plugin完成maven项目打包

    最近负责一个纯maven项目(项目需求尽量轻量化),需要自己完成打包工作. 因此,基于maven-compiler-plugin以及maven-shade-plugin完成项目的打包工作. 其中: m ...

  4. golang 的几个入门资料

    =====================视频=====================无闻 老师的<Go 编程基础>视频https://github.com/Unknwon/go-fun ...

  5. ORACLE基础之oracle锁(oracle lock mode)详解

    ORACLE里锁有以下几种模式: 0:none 1:null 空 2:Row-S 行共享(RS):共享表锁,sub share  3:Row-X 行独占(RX):用于行的修改,sub exclusiv ...

  6. express 将 Router 实例模块化

    为了更好的组织代码,将 Router 实例进行模块化,将 get / post 等快捷方式放在Router上,而不是 App 上,然后将该 Router 作为中间件,use 到 server.js 上 ...

  7. 网络流(2)——用Ford-Fullkerson算法寻找最大流

    寻找最大流 在大规模战争中,后勤补给是重中之重,为了尽最大可能满足前线的物资消耗,后勤部队必然要充分利用每条运输网,这正好可以用最大流模型解决.如何寻找一个复杂网络上的最大流呢? 直觉上的方案 一种直 ...

  8. CentOS7设置开机自启动方式

    方式一: # 在/etc/rc.d/rc.local文件中追加启动命令,该文件追加后,会随着机器自动后,自动运行文件中的命令 # vim /etc/rc.d/rc.local # 权限问题:在cent ...

  9. 运行java程序

    使用方式: java类名 硬盘上有HelloWorld.class,那么类名就是HelloWorld java HelloWorld[运行先到class路径下] 一定要注意:java命令后面跟的不是文 ...

  10. 谈谈你对OOM的理解?

    (1)整体架构 (1)ByteBuffer使用native方法,直接在堆外分配内存. 当堆外内存(也即本地物理内存)不够时,就会抛出这个异常     ----GC Direct buffer memo ...