V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Adia
V2EX  ›  Java

如何优雅的找出 ArrayList 中的重复元素?

  •  
  •   Adia · 2017-01-08 21:54:11 +08:00 · 7340 次点击
    这是一个创建于 2657 天前的主题,其中的信息可能已经有所发展或是发生改变。
    除了双循环这种,请问各位大神还有别的好方法吗?先谢过为敬
    第 1 条附言  ·  2017-01-08 22:48:58 +08:00
    不是去重,去重直接丢 set 就行啦。感谢各位
    36 条回复    2017-01-10 03:01:22 +08:00
    murmur
        1
    murmur  
       2017-01-08 21:59:44 +08:00   ❤️ 1
    为什么要双循环呢 第一次循环的时候如果你是往 map 里扔已经知道谁是重复的了
    Lonely
        2
    Lonely  
       2017-01-08 22:01:42 +08:00
    1 楼说的对
    slixurd
        3
    slixurd  
       2017-01-08 22:02:26 +08:00
    只有一个重复元素的话就是经典算法题吧
    反正就是空间 /时间看需要选哪个....
    不需要考虑空间就用 Map 吧.简单粗暴
    pupboss
        4
    pupboss  
       2017-01-08 22:03:36 +08:00
    如果数据量大,可以用 dict ,用空间换时间
    vchat
        5
    vchat  
       2017-01-08 22:04:49 +08:00
    如果可以的话 往 set 集合里面放, 然后判断返回值 然后将重复元素放在 arraylist 里
    palmers
        6
    palmers  
       2017-01-08 22:06:10 +08:00
    同意#5 的做法
    skywayman
        7
    skywayman  
       2017-01-08 22:11:32 +08:00
    最终是想找出,还是去掉多余重复的? 前者循环一次,MAP<Key,Count>计数就好,后者 Set 一次转换行. 如果使用 Stream,还可以在多 CPU 上开 Parallel.
    yidinghe
        8
    yidinghe  
       2017-01-08 22:19:29 +08:00 via Android   ❤️ 1
    删除重复元素:

    List result = list.stream().distinct().collect(Collectors.toList());
    Adia
        9
    Adia  
    OP
       2017-01-08 22:48:00 +08:00
    @murmur 请问是类似这个思路吗?
    @Lonely 请问是类似这个思路吗?
    @skywayman 请问是类似这个思路吗?



    public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("string1");
    list.add("string1");
    list.add("string1");
    list.add("string1");
    list.add("string3");
    list.add("string2");
    list.add("string2");
    HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
    for (String string : list) {
    if (hashMap.get(string) != null) {
    Integer value = hashMap.get(string);
    hashMap.put(string, value+1);
    } else {
    hashMap.put(string, 1);
    }
    }
    for (Entry<String, Integer> entry : hashMap.entrySet()) {
    String key=entry.getKey();
    Integer value= entry.getValue();
    if (value>1) {
    System.out.println("the element:"+key+" is repeat");
    }
    }

    }
    Adia
        10
    Adia  
    OP
       2017-01-08 22:48:30 +08:00
    @vchat 很好奇怎么写..
    wd
        11
    wd  
       2017-01-08 22:53:37 +08:00 via iPhone
    @Adia 第一个循环里面加一的时候 不就可以做第二个循环里面的事情了吗?....
    Adia
        12
    Adia  
    OP
       2017-01-08 23:04:33 +08:00
    @wd 的确。这代码统计了次数,但是题目中并没有说要统计
    Adia
        13
    Adia  
    OP
       2017-01-08 23:05:41 +08:00
    @wd 哦不..看错了。不好意思
    dtysky
        14
    dtysky  
       2017-01-08 23:07:39 +08:00 via Android   ❤️ 1
    没记错的话,有个方法是排序然后遍历……?
    如果允许额外空间,用 map
    dallaslu
        15
    dallaslu  
       2017-01-08 23:28:34 +08:00   ❤️ 1
    xlvecle
        16
    xlvecle  
       2017-01-09 00:28:43 +08:00 via iPhone   ❤️ 1
    list.removeAll(set(list))
    kooze
        17
    kooze  
       2017-01-09 00:50:58 +08:00
    rx
    bhagavad
        18
    bhagavad  
       2017-01-09 05:29:20 +08:00
    时间有要求还是空间有要求? ArrayList 中元素是什么类型?这些前提都得说清。
    hinkal
        19
    hinkal  
       2017-01-09 08:44:56 +08:00 via Android   ❤️ 1
    @bhagavad 元素类型倒是不用说,可以假定实现了 equals 接口或 compare 接口
    Adia
        20
    Adia  
    OP
       2017-01-09 08:48:38 +08:00
    @bhagavad 没有要求,请问不同元素类型的会有什么影响吗? String
    swim2sun
        21
    swim2sun  
       2017-01-09 10:23:06 +08:00
    Java8 可以这样写:

    List<String> list = Arrays.asList("1", "2", "3", "3");
    Map map = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    webcoder
        22
    webcoder  
       2017-01-09 10:25:44 +08:00
    简单点,把一个数组 join 成一个字符,然后循环 Contains 一下。
    局限点,不适用于对象数组。
    注意点,需要作好数据间隔符,防止拼接后数据混乱。
    vchat
        23
    vchat  
       2017-01-09 11:00:17 +08:00
    @Adia 使用 hashset #add 方法 如果是重复的元素则返回值为 fase [HashSet#add]( http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html#add(E))
    注意: 添加元素为非基本类型(包装类型)或 String 则需要实现 equals 和 hashCode 方法确保元素唯一性
    Adia
        24
    Adia  
    OP
       2017-01-09 11:22:01 +08:00
    @xlvecle 好像不行吧
    syasuker
        25
    syasuker  
       2017-01-09 11:50:25 +08:00
    也许可以 Java8 中使用 Stream 流思想进行过滤之类的
    xlvecle
        26
    xlvecle  
       2017-01-09 12:02:00 +08:00
    @Adia 昨天手写的,想当然了, removeAll 会全部 remove 掉,当做集合来处理
    zhidian
        27
    zhidian  
       2017-01-09 12:42:22 +08:00
    for str in list:
    if (str not in set) {
    set <- str
    } else {
    // dup
    }
    snnn
        28
    snnn  
       2017-01-09 12:43:23 +08:00 via Android
    sort
    misaka19000
        29
    misaka19000  
       2017-01-09 13:19:13 +08:00 via Android   ❤️ 1
    先排序后便利,时间复杂度 n log ( n )
    Perry
        30
    Perry  
       2017-01-09 13:22:44 +08:00 via iPhone
    优雅到底是什么意思?
    ooTwToo
        31
    ooTwToo  
       2017-01-09 13:24:33 +08:00   ❤️ 1
    同意楼上,先排序后再遍历,与上个元素比对; Java Stream 有去重函数可以方便很多~
    lovekohn
        32
    lovekohn  
       2017-01-09 13:28:06 +08:00
    排序后,遍历下相邻的两个是否相同
    fffflyfish
        33
    fffflyfish  
       2017-01-09 15:09:08 +08:00
    一楼说的对,这种时候就该用 hashmap,时间复杂度就是 O(n)
    fffflyfish
        34
    fffflyfish  
       2017-01-09 15:26:51 +08:00
    ![pic]( )
    如何,够不够优雅
    leopku
        35
    leopku  
       2017-01-09 15:27:15 +08:00   ❤️ 1
    // Guava
    List<Employee> employees = // ...
    Multimaps.index(employees, e -> e.getName())

    // Guava 另外一个版本
    List<Employee> employees = // ...
    Collection<Employee> filtered =
    Collections2.filter(employees, new Predicate<Employee>() {
    @Override
    public boolean apply(Employee e) {
    return e.getName().equals("John Doe");
    }
    });
    // if you want a List:
    List<Employee> filteredList = new ArrayList<>(filtered);


    // Java 8
    List<Employee> filteredList = employees.stream()
    .filter(e -> e.getName().equals("John Doe"))
    .collect(Collectors.toList());
    mingl0280
        36
    mingl0280  
       2017-01-10 03:01:22 +08:00
    //C#奇技淫巧
    ArrayList b = new ArrayList();
    Dictionary<int, int> x = new Dictionary<int, int>();
    foreach (int elem in a)
    {
    try
    {
    x.Add(elem, 0);
    }catch(Exception){
    b.Add(elem);
    }
    }
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2688 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 15:47 · PVG 23:47 · LAX 08:47 · JFK 11:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.