java取出重复数最多的前n条数据

前两天面试时有问到这个问题(读取一个文本文件中数据,每行是一条URL且存在URL重复,统计重复最多的前10条URL及其重复数量),因为紧张一时半会没想明白,下来后整理了下思路发现实现方式还是蛮多的,这里学习总结一下:

这种问题考的其实就是List和map的使用,这里就先贴上两种方法

第一种,使用Map.entrySet()方法,代码如下:

public static void (List<String> lists) {
        Map<String, Integer> maps = new HashMap<String, Integer>();
        /*for(String str:lists){
            if(maps.containsKey(str)){            //如果重复则将对应的value值加1
                maps.put(str,maps.get(str)+1);
            }else{
                maps.put(str,1);
            }
        }*/
        for (String str : lists) {
            if (!maps.containsKey(str)) {       //取出不重复的数据和对应的条数加入map<数据,条数>
                maps.put(str, Collections.frequency(lists, str));           //Collections.frequency方法计算数据在list中的数量
            }
        }
        List<Map.Entry<String, Integer>> result =
                new ArrayList<Map.Entry<String, Integer>>(maps.entrySet());
        Collections.sort(result, new Comparator<Map.Entry<String, Integer>>() {
            /*
            *使用匿名内部类重写排序算法
            * */
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return o2.getValue().compareTo(o1.getValue());            //根据每个Entry对象的value值排序
            }
        });

        System.out.println("result size: " + result.size() + " \n result: " + result.toString());
    }

lists参数值如下:

lists: [add: 1, add: 2, add: 3, add: 4, add: 5, add: 3, add: 7, add: 4, add: 3, add: 10, add: 11, add: 3, add: 13, add: 14, add: 3, add: 4, add: 17, add: 3, add: 19, add: 10]

方法结果如下:

result size: 12
        result: [add: 3=6, add: 4=3, add: 10=2, add: 17=1, add: 19=1, add: 13=1, add: 7=1, add: 14=1, add: 11=1, add: 5=1, add: 2=1, add: 1=1]

第二种:使用两个ArrayList对应存储(一个存储数据,一个存储数量,相互使用下标同步)排序,代码如下:

public static void staData2(List<String> lists){
        List<String> res=new ArrayList<String>();
        List<Integer> liss=new ArrayList<Integer>();
        /*for(int i=0;i<lists.size();i++){
            //查询数据在res结果集中是否存在,若存在则找到下标并将对应liss内相同下标的值加1
            if(res.contains(lists.get(i))){
                liss.set(res.indexOf(lists.get(i)),liss.get(res.indexOf(lists.get(i)))+1);
            }else{
                res.add(lists.get(i));
                liss.add(1);
            }
        }*/
        for(String str : lists){
            if(!res.contains(str)){
                res.add(str);
                liss.add(Collections.frequency(lists,str));
            }
        }
        int a=0;
        String s="";
        for(int i=0;i<liss.size()-1;i++){      //这里随便写了个排序,没考虑其他性能
            for(int j=i+1;j<liss.size();j++){
                if(liss.get(i)<liss.get(j)){
                    a=liss.get(i);
                    s=res.get(i);
                    liss.set(i,liss.get(j));    //liss和res的数据同步的,排序调换时,两个都要调换
                    res.set(i,res.get(j));
                    liss.set(j,a);
                    res.set(j,s);
                }
            }
        }
        System.out.println(res.toString());
        System.out.println(liss.toString());
    }

方法结果如下:

[add: 3, add: 4, add: 10, add: 2, add: 5, add: 7, add: 1, add: 11, add: 13, add: 14, add: 17, add: 19]
[6, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]

当然,第一种更为方便性能更好,还有其他实现方式这里就不写了,顺便复习下Map的使用

不过有个问题,在查看HashMap的源码时:entrySet方法是返回Entry的Set集合对象,源码如下:

    public Set<Map.Entry<K,V>> entrySet() {
        Set<Map.Entry<K,V>> es;
        return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
    }

HashMap中有个属性entrySet,这里返回的是entrySet属性的值对象,如果entrySet为null,则新建一个EntrySet对象赋值并返回;

但是在HashMap的源码中并没有找到给entrySet属性赋值或更改值的语句,如果这样的话,当HashMap中有映射对存在时,entrySet方法返回的entrySet属性中的值是从哪里来的,到现在还在疑惑,最近找工作都熬成夜猫子了,大半夜根本睡不着,现在更睡不着了,求大神解惑,谢谢!




猜你喜欢

转载自blog.csdn.net/qq_18259401/article/details/80102326
今日推荐