如何提高以下java方法的性能,以从Linkedlist中删除元素

时间:2012-05-07 19:56:39

标签: java multithreading performance

从Linkedlist中删除节点的线程安全方法。

 public void delete(String x, LinkedList<String> list)
   {
      String lock = "false";
        for (int i = 0; i < list.size(); i++) {
            synchronized (lock) {
                if (list.get(i).equals(x)) {
                    lock = "true";
                    list.remove(i);
                }
                lock = "false";
            }
        }
   }

非常感谢!

编辑:上面的方法是线程安全的,但其性能需要提高。这是一个面试问题。

7 个答案:

答案 0 :(得分:3)

  1. 在方法本地的对象上进行同步并没有真正做任何有用的事情。此外,覆盖对同步块内锁定的对象的引用是有目的的混淆。关于该代码的目的的一些解释可能有助于我们帮助您改进它:)

  2. 实际问题。 get(i)remove(i)都要求您将列表迭代到位置i。如果使用列表的实际迭代器和迭代器的remove方法,则只需迭代整个列表一次。

答案 1 :(得分:2)

主题安全的:

public void delete(String x, LinkedList<String> list) {
    synchronized (list) {
       for (Iterator<String> it = list.iterator(); it.hasNext();)
            if (it.next().equals(x)) it.remove();
    }
}

但是,很可能,你的问题不是线程安全。您在遍历列表时使用了list.delete()并获得了ConcurrentModificationException。如果是这种情况,请随意删除同步块。

答案 2 :(得分:1)

我会使用List.removeAll

List<String> list = new LinkedList<>();
list.addAll(Arrays.asList("a,b,c,d,a,b,c,d,e,a,b,a,b".split(",")));
System.out.println("Before removeAll(a) " + list);

list.removeAll(Collections.singleton("a"));

System.out.println("After removeAll " +list);

打印

Before removeAll(a) [a, b, c, d, a, b, c, d, e, a, b, a, b]
After removeAll [b, c, d, b, c, d, e, b, b]

答案 3 :(得分:0)

尝试为同步集合使用现成的Java Collections API功能。 Official documentation.

您还可以使用迭代器删除项目。正如文件所述:

  

如果使用显式迭代器,则必须调用迭代器方法   来自同步块内。不遵循这个建议可能会   导致不确定的行为。

答案 4 :(得分:0)

public void delete (String x, LinkedList<String> list) {

            synchronized (list) {
                Iterator<String> it = list.iterator();
                while (it.hasNext()) {
                    String y = it.next();
                    if (x.equals(y)) {
                        it.remove();
                    }
                }
            }
        }

答案 5 :(得分:0)

public void delete(String x, LinkedList<String> list){
    Set<String> target = Collections.singleton(x);
    synchronized (list) {
        list.removeAll( target );
    }
}

两件事:

  1. 对刚刚创建的字符串进行同步不会做任何事情(嗯,不完全是,因为"false"是一个实习字符串,所有在"false"上同步的代码片段都会被同步,但这是一种hackish方式获得应用程序范围的同步,可能根本不是你想要的。您应该在列表上进行同步。使用列表的每个人都应该在列表上进行同步。虽然最好的做法是首先使用同步集合,但不需要在使用代码中使用明确的synchronized块。
  2. removeAll通常是从集合中删除所有出现的一个或多个对象的最有效方法。在最坏的情况下,它相当于迭代集合并使用迭代器来移除项(这是LinkedList的情况),但对于某些实现(如ArrayList),它被设为效率更高。

答案 6 :(得分:0)