how2j.cn

本视频是解读性视频,所以希望您已经看过了本知识点的内容,并且编写了相应的代码之后,带着疑问来观看,这样收获才多。 不建议一开始就观看视频



7分15秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)



示例 1 : 元素不能重复   
示例 2 : 没有顺序   
示例 3 : 遍历   
示例 4 : HashSet和HashMap的关系   
示例 5 : 练习-HashSet   
示例 6 : 答案-HashSet   

示例 1 :

元素不能重复

Set中的元素,不能重复
package collection; import java.util.HashSet; public class TestCollection { public static void main(String[] args) { HashSet<String> names = new HashSet<String>(); names.add("gareen"); System.out.println(names); //第二次插入同样的数据,是插不进去的,容器中只会保留一个 names.add("gareen"); System.out.println(names); } }
package collection;
 
import java.util.HashSet;
 
public class TestCollection {
    public static void main(String[] args) {
        
    	HashSet<String> names = new HashSet<String>();
    	
    	names.add("gareen");
    	
    	System.out.println(names);
    	
    	//第二次插入同样的数据,是插不进去的,容器中只会保留一个
    	names.add("gareen");
    	System.out.println(names);
    }
}
示例 2 :

没有顺序

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

HashSet的具体顺序,既不是按照插入顺序,也不是按照hashcode的顺序。关于hashcode有专门的章节讲解: hashcode 原理

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

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


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


换句话说,同样是插入0-9到HashSet中, 在JVM的不同版本中,看到的顺序都是不一样的。 所以在开发的时候,不能依赖于某种臆测的顺序,这个顺序本身是不稳定的
没有顺序
package collection; import java.util.HashSet; public class TestCollection { public static void main(String[] args) { HashSet<Integer> numbers = new HashSet<Integer>(); numbers.add(9); numbers.add(5); numbers.add(1); // Set中的元素排列,不是按照插入顺序 System.out.println(numbers); } }
package collection;

import java.util.HashSet;

public class TestCollection {
	public static void main(String[] args) {
		HashSet<Integer> numbers = new HashSet<Integer>();

		numbers.add(9);
		numbers.add(5);
		numbers.add(1);

		// Set中的元素排列,不是按照插入顺序
		System.out.println(numbers);

	}
}
示例 3 :

遍历

Set不提供get()来获取指定位置的元素
所以遍历需要用到迭代器,或者增强型for循环
package collection; import java.util.HashSet; import java.util.Iterator; public class TestCollection { public static void main(String[] args) { HashSet<Integer> numbers = new HashSet<Integer>(); for (int i = 0; i < 20; i++) { numbers.add(i); } //Set不提供get方法来获取指定位置的元素 //numbers.get(0) //遍历Set可以采用迭代器iterator for (Iterator<Integer> iterator = numbers.iterator(); iterator.hasNext();) { Integer i = (Integer) iterator.next(); System.out.println(i); } //或者采用增强型for循环 for (Integer i : numbers) { System.out.println(i); } } }
示例 4 :

HashSet和HashMap的关系

通过观察HashSet的源代码(如何查看源代码
可以发现HashSet自身并没有独立的实现,而是在里面封装了一个Map.
HashSet是作为Map的key而存在的
而value是一个命名为PRESENT的static的Object对象,因为是一个类属性,所以只会有一个。

private static final Object PRESENT = new Object();
package collection; import java.util.AbstractSet; import java.util.HashMap; import java.util.Iterator; import java.util.Set; public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { //HashSet里封装了一个HashMap private HashMap<E,Object> map; private static final Object PRESENT = new Object(); //HashSet的构造方法初始化这个HashMap public HashSet() { map = new HashMap<E,Object>(); } //向HashSet中增加元素,其实就是把该元素作为key,增加到Map中 //value是PRESENT,静态,final的对象,所有的HashSet都使用这么同一个对象 public boolean add(E e) { return map.put(e, PRESENT)==null; } //HashSet的size就是map的size public int size() { return map.size(); } //清空Set就是清空Map public void clear() { map.clear(); } //迭代Set,就是把Map的键拿出来迭代 public Iterator<E> iterator() { return map.keySet().iterator(); } }
示例 5 :

练习-HashSet

Or  姿势不对,事倍功半! 点击查看做练习的正确姿势
比较字符串章节,有一个同样的练习
创建一个长度是100的字符串数组
使用长度是2的随机字符填充该字符串数组
统计这个字符串数组里重复的字符串有多少种
使用HashSet来解决这个问题
练习-HashSet
示例 6 :

答案-HashSet

在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
本视频是解读性视频,所以希望您已经看过了本答案的内容,带着疑问来观看,这样收获才多。 不建议一开始就观看视频

2分44秒 本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)


package collection; import java.util.HashSet; public class TestCollection { public static void main(String[] args) { String[] ss = new String[100]; // 初始化 for (int i = 0; i < ss.length; i++) { ss[i] = randomString(2); } // 打印 for (int i = 0; i < ss.length; i++) { System.out.print(ss[i] + " "); if (19 == i % 20) System.out.println(); } HashSet<String> result = new HashSet<>(); for (String s1 : ss) { int repeat = 0; for (String s2 : ss) { if (s1.equalsIgnoreCase(s2)) { repeat++; if (2 == repeat) { // 当repeat==2的时候,就找到了一个非己的重复字符串 result.add(s2); break; } } } } System.out.printf("总共有 %d种重复的字符串%n", result.size()); if (result.size() != 0) { System.out.println("分别是:"); for (String s : result) { System.out.print(s + " "); } } } private static String randomString(int length) { String pool = ""; for (short i = '0'; i <= '9'; i++) { pool += (char) i; } for (short i = 'a'; i <= 'z'; i++) { pool += (char) i; } for (short i = 'A'; i <= 'Z'; i++) { pool += (char) i; } char cs[] = new char[length]; for (int i = 0; i < cs.length; i++) { int index = (int) (Math.random() * pool.length()); cs[i] = pool.charAt(index); } String result = new String(cs); return result; } }


HOW2J公众号,关注后实时获知布最新的教程和优惠活动,谢谢。


问答区域    
2018-11-26 作业
Memory_123



Q3 eb e3 ki A3 Dp F0 np Mh ST HV n9 rR lO Rh r7 y1 9L K1 yO Yr FA Nc mh a6 I3 Ny jK ag VO 0E Qq 40 iD 2A EX DM D8 cb kh 0p EN FB vC ln jY jS 51 Us dJ WV Gz 0O YR zt aT nn s5 RY X9 Gn MS h1 P3 wH 4z GF KW 6g wd h2 7Z mm Gn R8 BR FT K1 GM Na ag Sa 7N hP uH tf 71 XS en gl 66 6K rt Ft Od Rz cv 6L oo hN 总共有3种重复的字符串,其分别为: [Gn, K1, ag]
public static void main(String[] args){
String[] str = new String[10*10];
        for (int i = 0;i<str.length;i++){
            str[i] = random();
            if (i%20 == 0){
                System.out.println();
            }
            System.out.format(str[i]+"\t");
        }
        System.out.println();
        HashSet<String> stringHashSet = new HashSet<>();
        boolean flag = true;
        List<String> list = new ArrayList<>();
        for (int i= 0 ;i<str.length;i++){
            flag = stringHashSet.add(str[i]);
           if (! flag){
               list.add(str[i]);
           }
        }
        System.out.printf("总共有%d种重复的字符串,其分别为:%n", list.size());
        System.out.println(list);
}

 public static String random(){
        char[] chars = new char[2];
        int start = '0';
        int end = 'z'+1;
        for (int i = 0 ;i < chars.length;i++){
            while (true){
                char c = (char) (Math.random()*(end-start)+start);
                if (Character.isLetter(c) || Character.isDigit(c)){
                    chars[i] = c;
                    break;
                }
            }
        }
        String res = String.valueOf(chars);
        return res;
    }

							


2 个答案

qas12 答案时间:2018-12-06
你这个random会有除了字母和数字的其他符号的,详细请看美国信息交换标准代码,

Deutschland1990 答案时间:2018-12-05
main方法中的 list 要被定义为HashSet。你定义为ArrayList,如果一个字符串出现3次或者3次以上的重复就会出问题,你可以试试




答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2018-11-15 查找重複元素
xwyjrcmbs



5O Fw AJ G6 Hc Ff 0C dc 9p 89 qG 1Y Yp QO A4 1Y sL gh j7 x2 2b 4P T1 RD Gx T9 0c Ms R7 2h 70 FV Ji oh AI 0g qm cs 4T Jz 5B Gq RY dg CP pk Ko EK Ad x5 KE t3 jb tv wp ot YC jU QA hd UO KA lQ Y9 BV Bh n8 Aa lG JZ nk CR bk tM Ph nH N4 pb dN 2T 0p mV yx Xl 8m kc xJ IN v0 pn 7U nO sU Y0 Dl ko Z5 Gu Bi la 重复元素是 1Y hashset的长度是99
public static void main(String[] args) {
		 String aString[] = initStringArr(100);
		 String msg = "重复元素是";
		 HashSet<String> hashSet = new HashSet<>();
		 for(int i =0;i<aString.length;++i){
			
			 boolean f = hashSet.add(aString[i]);
			 if(!f){
				 msg +=" "+aString[i];
			 }
			 if(i%10==0)
				 System.out.println();
			 System.out.print(aString[i]+" ");
		 }
		 System.out.println();
		 System.out.println(msg+" hashset的长度是"+hashSet.size());
		 
		
	}
	public static String[] initStringArr(int length){
		String stringArr[] = new String[100];
		String inits = "0123456789qwertyuioplkjhgfdsazxcvbnmXZCVBNMLKJHGFDSAQWERTYUIOP";
		for(int i =0;i<length;++i){
			int ranNum = (int)(Math.random()*inits.length());
			int ranNum2 = (int)(Math.random()*inits.length());
			
			stringArr[i] = inits.charAt(ranNum)+""+inits.charAt(ranNum2)+"";
		
		}
		return stringArr;
	}

							






答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2018-10-29 作业
2018-10-29 作业
2018-10-21 交作业
2018-10-21 交作业
2018-10-19 HashSet自带contains方法
2018-09-24 作业!
2018-09-03 作业
2018-08-31 为什么要用equalsIngoreCase()方法呢
2018-08-31 作业
2018-08-28 交作业
2018-08-06 答案
2018-07-31 交作业
2018-07-11 为啥我照站长的答案改的,hashmap的性能和arraylist是一样的啊?
2018-04-20 用HashSet的add方法,当里面有重复的时候返回false,根据这个判断
2018-03-07 练习题没有用到HashSet的特性
2018-01-10 hashSet存在的意义
2017-12-11 22行改成这样会不会提高点效率?
2017-12-11 第13行,也就是第一次for循环的时候添加一个判断包含语句是不是会提高点效率?
2017-11-27 用HashSet自带的contains方法感觉思路不会辣么绕。。
2017-10-27 作业
2017-09-27 站长大大,我按自己想法写了一个答案,你看看对不
2017-07-29 Hashset和set有什么区别啊
2017-02-10 答案没有用 HashSet 啊




提问之前请登陆
关于 JAVA 中级-集合框架-HashSet 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 902680467
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: http://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图