繁体   English   中英

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

[英]how to improve the performance of the following java method to delete elements from a 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";
            }
        }
   }

非常感谢!

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

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

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

线程安全的:

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 在这种情况下,请随时删除同步块。

我会用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]

尝试对同步集合使用开箱即用的Java集合API功能。 官方文件。

而且,您还可以使用迭代器删除项目。 如文档所述:

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

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();
                    }
                }
            }
        }
public void delete(String x, LinkedList<String> list){
    Set<String> target = Collections.singleton(x);
    synchronized (list) {
        list.removeAll( target );
    }
}

两件事情:

  1. 在您刚创建的字符串上进行同步不会执行任何操作(嗯,不完全是,因为"false"是一个内部字符串,所有在"false"进行同步的代码段都将被同步,但这是获得应用程序范围内同步的一种不可靠的方式,可能根本没有您的意图)。 您应该在列表上进行同步。 使用列表的每个人都应该在列表上进行同步。 尽管更好的做法是首先使用同步集合,但在使用代码中无需显式synchronized块。
  2. removeAll通常是从集合中删除所有出现的一个或多个对象的最有效方法。 在最坏的情况下,这等效于遍历集合并使用迭代器删除项目(在LinkedList的情况下),但是对于某些实现(例如ArrayList ),这样做使其效率更高。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM