arrayList 的removeAll效率问题

Jone_wan 2012-12-05 04:52:52
我有两个list,listA和listB,想分别去掉两个list相同的部分,调用listA.removeAll(listB)可以得到解决,可以list的大小上万以后,运行的速度很慢,我换用linkedList,好像速度提升的不是很明显,不知哪位大侠有好的方法指导下?
...全文
813 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
lzh2320 2015-08-05
  • 打赏
  • 举报
回复
引用 14 楼 david_li_sg 的回复:
在我本机测试, 挺快的. 但有一个问题, 如果原来的list里面有重复的数字, 都被清除了, 不知道这个对你的具体问题有没有影响.

    public static void main(String[] args) {
        int max_len = 50000;
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        ArrayList<Integer> list2 = new ArrayList<Integer>();
        for (int i=0; i<max_len; i++) {
            list1.add((int)(Math.random()*max_len));
            list2.add((max_len/2)+(int)(Math.random()*max_len));
        }
        
        System.out.printf("list1:%d, list2:%d\n", list1.size(), list2.size());
        long start = System.currentTimeMillis();
        
        HashSet<Integer> set_all = new HashSet<Integer>();
        for (int i=0; i<list1.size(); i++) {
            set_all.add(list1.get(i));
        }
        HashSet<Integer> set_dup = new HashSet<Integer>();
        ArrayList<Integer> list2_clean = new ArrayList<Integer>();
        for (int i=0; i<list2.size(); i++) {
            if (set_all.add(list2.get(i))) {  //in list2 but not in list1
                list2_clean.add(list2.get(i));
            } else {
                set_dup.add(list2.get(i));  //in list2 and also in list1
            }
        }
        ArrayList<Integer> list1_clean = new ArrayList<Integer>();
        for (int i=0; i<list1.size(); i++) {
            if (set_dup.add(list1.get(i))) {  //in list1 but not in the duplicated set
                list1_clean.add(list1.get(i));
            }
        }
        
        long end = System.currentTimeMillis();
        System.out.printf("list1 clean:%d, list2 clean:%d\n", list1_clean.size(), list2_clean.size());
        System.out.printf("time spent : %dms\n", end-start);
    }
达到的效果大概是 结果1: list1[{1},{3},{3},{5}]list2[{2},{3},{4}] → list1[{1},{5}]list2[{2},{4}] 14楼担心的楼主想要的结果是 结果2: list1[{1},{3},{5}]list2[{2},{4}] 如果调用java自带的,一般流程之后也是结果1
kangxingang 2013-06-04
  • 打赏
  • 举报
回复
[quote=引用 14 楼 david_li_sg 的回复:] 在我本机测试, 挺快的. 但有一个问题, 如果原来的list里面有重复的数字, 都被清除了, 不知道这个对你的具体问题有没有影响. 这个......
蒙奇D路飞 2012-12-31
  • 打赏
  • 举报
回复
引用 14 楼 david_li_sg 的回复:
在我本机测试, 挺快的. 但有一个问题, 如果原来的list里面有重复的数字, 都被清除了, 不知道这个对你的具体问题有没有影响. Java code?123456789101112131415161718192021222324252627282930313233343536 public static void main(String[] args) { ……
这位哥的方法好快啊,比自带的 removeAll还快呢!
初学者多指教 2012-12-07
  • 打赏
  • 举报
回复
在我本机测试, 挺快的. 但有一个问题, 如果原来的list里面有重复的数字, 都被清除了, 不知道这个对你的具体问题有没有影响.

    public static void main(String[] args) {
        int max_len = 50000;
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        ArrayList<Integer> list2 = new ArrayList<Integer>();
        for (int i=0; i<max_len; i++) {
            list1.add((int)(Math.random()*max_len));
            list2.add((max_len/2)+(int)(Math.random()*max_len));
        }
        
        System.out.printf("list1:%d, list2:%d\n", list1.size(), list2.size());
        long start = System.currentTimeMillis();
        
        HashSet<Integer> set_all = new HashSet<Integer>();
        for (int i=0; i<list1.size(); i++) {
            set_all.add(list1.get(i));
        }
        HashSet<Integer> set_dup = new HashSet<Integer>();
        ArrayList<Integer> list2_clean = new ArrayList<Integer>();
        for (int i=0; i<list2.size(); i++) {
            if (set_all.add(list2.get(i))) {  //in list2 but not in list1
                list2_clean.add(list2.get(i));
            } else {
                set_dup.add(list2.get(i));  //in list2 and also in list1
            }
        }
        ArrayList<Integer> list1_clean = new ArrayList<Integer>();
        for (int i=0; i<list1.size(); i++) {
            if (set_dup.add(list1.get(i))) {  //in list1 but not in the duplicated set
                list1_clean.add(list1.get(i));
            }
        }
        
        long end = System.currentTimeMillis();
        System.out.printf("list1 clean:%d, list2 clean:%d\n", list1_clean.size(), list2_clean.size());
        System.out.printf("time spent : %dms\n", end-start);
    }
zxj828282 2012-12-07
  • 打赏
  • 举报
回复
top top top
展S开K双Y翼 2012-12-07
  • 打赏
  • 举报
回复
java 做这个,怎么都快不了,native的方法是最快的了
Jone_wan 2012-12-07
  • 打赏
  • 举报
回复
引用 6 楼 zhou9898 的回复:
引用 5 楼 zxhcloth 的回复: 1、遍历list1到中间队列或者map,并设置标记(就是累加每个对象的数量) 2、遍历list2到上述的中间队列或者map,并设置标记(就是累加每个对象的数量) 3、遍历中间队列或者map的key(也就是keySet),判断标记,如果标记大于1,删除此对象 4、剩下的就是你要的结果。 这个貌似只是解决了前面的问题。 后面的A和Blist还没……
我看过源码了,removeAll实现定义在AbstractCollection里面,实现如下

public boolean removeAll(Collection<?> c) {
	boolean modified = false;
	Iterator<?> e = iterator();
	while (e.hasNext()) {
	    if (c.contains(e.next())) {
		e.remove();
		modified = true;
	    }
	}
	return modified;
    }
ArrayList和LinkedList都继承了AbstractCollection,没有覆盖removeAll方法。 HashSet的父类AbstractSet有覆盖removeAll方法,不过思路好像也差不多。
Jone_wan 2012-12-07
  • 打赏
  • 举报
回复
引用 14 楼 david_li_sg 的回复:
在我本机测试, 挺快的. 但有一个问题, 如果原来的list里面有重复的数字, 都被清除了, 不知道这个对你的具体问题有没有影响. Java code ? 12345678910111213141516171819202122232425262728293031323334353637 public static void main(String[] a……
感谢这位仁兄的回答,刚好我的数据都是不重复的,试运行了一下,50000条数据只用了15ms,很给力,给我两万多条数据,绰绰有余了。
YECHWNG 2012-12-06
  • 打赏
  • 举报
回复
上网查一下list本事提供了那些方法
YECHWNG 2012-12-06
  • 打赏
  • 举报
回复
如果用嵌套的两个for循环的话,效率应该不是很高,你有没有上网查过啊
oO临时工Oo 2012-12-06
  • 打赏
  • 举报
回复
引用 3 楼 Jone_wan 的回复:
引用 1 楼 trocp 的回复:把两个list中的数据取出来放到一个HashSet中谢谢,可能我没描述清楚,我是想把重复的部分去掉,两个list只剩下没有交集的元素。例如:ListA{1,2,3} listB(2,3,4),得到的结果是ListA{1},ListB{4}
想在java.util.List的基础上做你所说的事情,一般来讲,没有什么比调用List自己的方法更好的了
程序员一灯 2012-12-05
  • 打赏
  • 举报
回复
引用 5 楼 zxhcloth 的回复:
1、遍历list1到中间队列或者map,并设置标记(就是累加每个对象的数量) 2、遍历list2到上述的中间队列或者map,并设置标记(就是累加每个对象的数量) 3、遍历中间队列或者map的key(也就是keySet),判断标记,如果标记大于1,删除此对象 4、剩下的就是你要的结果。
这个貌似只是解决了前面的问题。 后面的A和Blist还没有相减。。。。去重。。。 后面那个没看到源码不知道为什么性能不行。。建议楼猪童鞋看看源码。。。。(因为找了好长时间没找到其中的源码。。楼猪童鞋自己慢慢找找。。找到了引用我一下。。3颗屎。、。)
zxhcloth 2012-12-05
  • 打赏
  • 举报
回复
1、遍历list1到中间队列或者map,并设置标记(就是累加每个对象的数量) 2、遍历list2到上述的中间队列或者map,并设置标记(就是累加每个对象的数量) 3、遍历中间队列或者map的key(也就是keySet),判断标记,如果标记大于1,删除此对象 4、剩下的就是你要的结果。
Jone_wan 2012-12-05
  • 打赏
  • 举报
回复
引用 2 楼 cl61917380 的回复:
引用 1 楼 trocp 的回复: 把两个list中的数据取出来放到一个HashSet中 如果存的是对象,需要重写对象的hashcode和equals方法。
这个我已经重写了
Jone_wan 2012-12-05
  • 打赏
  • 举报
回复
引用 1 楼 trocp 的回复:
把两个list中的数据取出来放到一个HashSet中
谢谢,可能我没描述清楚,我是想把重复的部分去掉,两个list只剩下没有交集的元素。例如:ListA{1,2,3} listB(2,3,4),得到的结果是ListA{1},ListB{4}
coooliang 2012-12-05
  • 打赏
  • 举报
回复
引用 1 楼 trocp 的回复:
把两个list中的数据取出来放到一个HashSet中
如果存的是对象,需要重写对象的hashcode和equals方法。
oO临时工Oo 2012-12-05
  • 打赏
  • 举报
回复
把两个list中的数据取出来放到一个HashSet中

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧