黑马程序员技术交流社区
标题:
考题举一反五秒变大神:如何去除map所有重复值(附方法及详解
[打印本页]
作者:
378657357
时间:
2016-9-18 00:44
标题:
考题举一反五秒变大神:如何去除map所有重复值(附方法及详解
本帖最后由 378657357 于 2016-9-26 01:44 编辑
package com.heima.test;
import java.util.HashMap;
/*
去除双列集合中所有重复的值
附5种方法代码、思路(详细注释)
*/
public class Ex_Text1 {
public static void main(String[] args) throws Exception {
HashMap<Integer,String> hm = new HashMap<>();
//添加了20个测试数据,有相邻重复的,有间隔重复的,确保准确性,觉得不够欢迎继续添加测试
hm.put(1, "11");
hm.put(2, "11");
hm.put(3, "11");
hm.put(4, "22");
hm.put(5, "22");
hm.put(6, "33");
hm.put(7, "11");
hm.put(8, "22");
hm.put(9, "22");
hm.put(10, "44");
hm.put(11, "55");
hm.put(12, "77");
hm.put(13, "33");
hm.put(14, "44");
hm.put(15, "44");
hm.put(16, "66");
hm.put(17, "88");
hm.put(18, "99");
hm.put(19, "55");
hm.put(20, "11");
//第一种是用集合交换的思想来完全去重的
System.out.println(quchong1(hm));
//后面的四种总体思想都是将集合的值全部汇总到一个字符串中,再对其进行操作、判断是否重复的操作
//字符串indexOf和lastIndexOf查找判断是否重复
System.out.println(quchong2(hm));
//用str.indexOf(String str); str.indexOf(String str, index fromIndex);方法判断处理
System.out.println(quchong3(hm));
//用str.substring(beginIndex); str.contains(String str); str.indexOf(String str);方法判断处理
System.out.println(quchong4(hm));
//字符串数组选择排序比较原理,发现相等的就一键清理
System.out.println(quchong5(hm));
}
//去除双列集合所有重复值的方法1
private static HashMap<Integer, String> quchong1(HashMap<Integer, String> hm) {
//传入要完全去重的集合hm,创建完全去重的集合hhmm,以及过渡集合hm1
//过渡集合hm1泛型和原集合hm不同,因为hm1的键要装的是hm的值,hm1的值就是记录hm的值的出现的次数(有点绕,但是需要理解)
HashMap<Integer, String> hhmm = new HashMap<>();
HashMap<String, Integer> hm1 = new HashMap<>();
for (Integer key : hm.keySet()) {
String xinkey = hm.get(key);
hm1.put(xinkey, hm1.containsKey(xinkey) ? hm1.get(xinkey)+1 : 1);
}
//将原集合进行遍历,如果有过渡集合中的键,且其对应的值为1(只出现了1次,即代表不重复的意思),就将他添加到新集合hhmm中输出
for (Integer key : hm.keySet()) {
if (hm1.containsKey(hm.get(key)) && hm1.get(hm.get(key)) == 1) {
hhmm.put(key, hm.get(key));
}
}
return hhmm;
}
//去除双列集合所有重复值的方法2
private static HashMap<Integer, String> quchong2(HashMap<Integer, String> hm) {
HashMap<Integer, String> hhmm = new HashMap<Integer, String>();
//遍历双列集合,将需要去重的集合的值全部汇集到字符串str中,值与值之间用空格隔开
String str = "";
for (Integer key : hm.keySet()) {
str = str + hm.get(key) + " ";
}
//System.out.println(str); //要查看汇总完后的字符串str,解封此注释
//将字符串用空格切开,其实就是得到了原集合的各个值的String形式,下面就对其进行去重判断操作
//思路: 比如这个字符串是11 22 33 22 22 44
//如果不重复,那么indexOf和lastIndexOf拿到的索引肯定相同(一个是从前往后找匹配的索引,一个是从后往前找匹配的索引)
//如果重复了,那么拿到的索引肯定不同,例如str.indexOf("22")拿到的是3,而str.lastIndexOf("22")是12
String[] arr = str.split(" ");
for (int i = 0; i < arr.length; i++) {
if (str.indexOf(arr
) != str.lastIndexOf(arr
)) {
//只要重复了,就把这个重复的值意见替换成""(相当于清除掉了)
str = str.replaceAll(arr
, "");
}
}
//System.out.println(str); //要查看去重完后的字符串str,解封此注释,字符串中有空格,但那都不是事儿
//将去重后的字符串里的值和原集合值比对(都要转成字符串形式),如果原集合中有这个字符串中的值,那就是不重复的,再添加到新集合输出
for (Integer key : hm.keySet()) {
if (str.contains(hm.get(key).toString())) {
hhmm.put(key, hm.get(key));
}
}
return hhmm;
}
//去除双列集合所有重复值的方法3
private static HashMap<Integer, String> quchong3(HashMap<Integer,String> hm) {
HashMap<Integer, String> hhmm = new HashMap<Integer, String>();
//这里步骤同方法1,用一个字符串接收原集合的所有的值,中间用空格隔开
String str = "";
for (Integer key : hm.keySet()) {
str = str + hm.get(key) + " ";
}
/* 要用到的方法
indexOf方法1:str.indexOf("需要搜索并返回其对应索引的对象");
indexOf方法2:str.indexOf("对象(详解见上行)", "从第几个索引开始往后找这个对象");
原理:如果这个对象只出现了一次,那么用indexOf方法2的话,在这个对象第一次出现的索引之后用再开始找,
那么返回的就是-1(如果不重复就返回-1,如果有重复的,indexOf方法2就会返回这个重复值第二次出现的索引位置)
字符串索引去重法,从第一个值后的索引找,如果他是唯一的,那就得返回-1.
不是-1,那就是有重复的,一键清理
思路举例: 比如字符串是11 22 33 44 33 22 11 55 66
我用indexOf方法1:str.indexOf("22"); 给我返回索引3
我再以这个索引为基础加上这个对象的长度,作为起始索引,调用indexOf方法2:indexOf方法2:str.indexOf("22",这个对象的长度+他第一次出现的索引);
因为22是重复的,所以调用方法2,他又给我返回索引15,我就这么调用方法1和2各一次就行,重复的就一键删除,不要管他出现多少次 */
String[] arr = str.split(" ");
for (int i = 0; i < arr.length; i++) {
if (str.indexOf(arr
, str.indexOf(arr
)+arr
.length()) != -1) {
str = str.replaceAll(arr
, "");
}
}
//将去重后的字符串里的值和原集合值比对,如果原集合中有这个字符串中的值,那就是不重复的,再添加到新集合输出
for (Integer key : hm.keySet()) {
if (str.contains(hm.get(key))) {
hhmm.put(key, hm.get(key));
}
}
return hhmm;
}
//去除双列集合所有重复值的方法4:用str.substring(beginIndex); str.contains(String str); str.indexOf(String str);方法判断处理
private static HashMap<Integer, String> quchong4(HashMap<Integer, String> hm) {
HashMap<Integer, String> hhmm = new HashMap<Integer, String>();
//遍历双列集合,将需要去重的集合的值全部汇集到字符串str中,值与值之间用空格隔开
String str = "";
for (Integer key : hm.keySet()) {
str = str + hm.get(key) + " ";
}
//方法思路,如果重复了,那么我下面这句判断语句肯定就是true,然后我就进行一键删除所有重复的
//原理:最外层方法str.substring(截取第一个需要判断是否重复的值arr
的索引后面)再.contains(arr
)是否还包含,如果还包含,那么肯定是重复的
String[] arr = str.split(" ");
for (int i = 0; i < arr.length; i++) {
//substring括号里的意思就是需要判断是否重复的值arr
第一次出现的地方的索引(记住索引要加上arr
其长度)开始
if (str.substring(str.indexOf(arr
)+arr
.length()).contains(arr
)) {
str = str.replaceAll(arr
, "");
}
}
//System.out.println(str); //要查看去重完后的字符串str,解封此注释,字符串中有空格,但那都不是事儿
//将去重后的字符串里的值和原集合值比对(都要转成字符串形式),如果原集合中有这个字符串中的值,那就是不重复的,再添加到新集合输出
for (Integer key : hm.keySet()) {
if (str.contains(hm.get(key).toString())) {
hhmm.put(key, hm.get(key));
}
}
return hhmm;
}
//去除双列集合所有重复值的方法5:字符串数组选择排序原理(冒泡排序不行)比较,发现相等的就一键清理
//(和这个选择排序原理类似,他是充分判断大小,符合就交换,我的是充分判断大小,如果相等(重复),那么我就删除原字符串中重复的,不是删除数组)
private static HashMap<Integer, String> quchong5(HashMap<Integer, String> hm) {
HashMap<Integer, String> hhmm = new HashMap<Integer, String>();
//遍历双列集合,将需要去重的集合的值全部汇集到字符串str中,值与值之间用空格隔开
String str = "";
for (Integer key : hm.keySet()) {
str = str + hm.get(key) + " ";
}
//选择排序原理,我拿出数组中第一个(原集合值的String形式)分别与后面的去比较,发现有重复的,我就删除,然后继续第二个第二三个直至循环完充分比较
String[] arr = str.split(" ");
for (int i = 0; i < arr.length-1; i++) {
for (int j = 1+i; j < arr.length; j++) {
if (arr
.equals(arr[j])) {
str = str.replaceAll(arr[j], "");
}
}
}
//将去重后的字符串里的值和原集合值比对(都要转成字符串形式),如果原集合中有这个字符串中的值,那就是不重复的,再添加到新集合输出
for (Integer key : hm.keySet()) {
if (str.contains(hm.get(key).toString())) {
hhmm.put(key, hm.get(key));
}
}
return hhmm;
}
}
作者:
378657357
时间:
2016-9-18 00:47
自顶沙发
作者:
风轻云淡139
时间:
2016-9-18 00:50
好多代码啊~~~~
作者:
378657357
时间:
2016-9-18 01:43
风轻云淡139 发表于 2016-9-18 00:50
好多代码啊~~~~
解决问题就要举一反三~~~
我这里是举一反五,代码当然会有点多...
第一种方法是利用双列集合的特性交换交叉完全去重
第二到第五种方法都是利用字符串配合正则表达式完全去重的思想,先把原map集合的值遍历全部添加到一个字符串中(利用空格隔开以区分),然后利用第二到第四种方法判断字符串中有没有重复的,有就用正则表达式删除重复的(replaceAll把符合的重复的子字符串全部替换成空串""达到去重),然后拿这个去重之后的字符串去遍历原map集合比对,如果去重后的字符串里包含map中的值,那么就不是重复的,添加到一个新map集合中.以此达到完全去重的效果.
(因为我对字符串进行处理切割都是利用原集合键里没有的符号空格,所以当原map集合值没有空格就行)
这是一个点招面试题,从朋友那边听来的
方法虽多,掌握第一种,就对集合有一个比较熟悉的了解认识和运用了.
如果能理解第二到四种字符串去重所利用的操作方法和思想,你的String相关操作绝对是没有什么问题的!
作者:
为了王者上JAVA
时间:
2016-9-28 01:13
方法一用集合好保险代码思路也很清晰啊
后面几个感觉有些类似啊,就是变成了字符串去重?
作者:
kansyoukyou
时间:
2016-9-28 10:37
好多,看不过来~··
作者:
378657357
时间:
2016-9-28 10:55
kansyoukyou 发表于 2016-9-28 10:37
好多,看不过来~··
复制粘贴到eclipse里头一个一个方法分解看,我这里是五种,你要是能一下子都看懂那还怎么玩...
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2