简体   繁体   English

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

[英]how to improve the performance of the following java method to delete elements from a Linkedlist

A thread safe method to delete nodes 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";
            }
        }
   }

Many thanks! 非常感谢!

Edit: the above method is thread safe but its performance needs to improve. 编辑:上面的方法是线程安全的,但其性能需要提高。 It is an interview question. 这是一个面试问题。

  1. synchronizing on an object that is local to the method isn't really doing anything useful. 在方法本地的对象上进行同步实际上并没有做任何有用的事情。 Also, overwriting the reference to the object you're locking on inside the synchronized block is confusing in purpose. 另外,覆盖对您在同步块内锁定的对象的引用,在目的上会造成混淆。 Some explanation on the purpose of that code might help us help you improve it :) 关于该代码的目的的一些解释可能会帮助我们帮助您改进它:)

  2. The actual question. 实际的问题。 get(i) and remove(i) both require you to iterate the list out to position i. get(i)remove(i)都需要您迭代列表以将其定位到i。 If you use the list's actual iterator and the iterator's remove method, you will only have to iterate the entire list once. 如果使用列表的实际迭代器和迭代器的remove方法,则只需要迭代整个列表一次。

Thread-safe: 线程安全的:

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();
    }
}

But, in all probability, your problem wasn't thread safety. 但是,很可能您的问题不是线程安全。 You used list.delete() while iterating through the list and got ConcurrentModificationException . 您在遍历列表时使用了list.delete()并获得了ConcurrentModificationException If that is the case, feel free to remove synchronized block. 在这种情况下,请随时删除同步块。

I would use List.removeAll 我会用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);

prints 版画

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]

Try using out-of-box Java Collections API functionality for synchronized collections. 尝试对同步集合使用开箱即用的Java集合API功能。 Official documentation. 官方文件。

And also you could use an iterator to remove items. 而且,您还可以使用迭代器删除项目。 As documentation states: 如文档所述:

If an explicit iterator is used, the iterator method must be called from within the synchronized block. 如果使用显式迭代器,则必须从同步块内调用迭代器方法。 Failure to follow this advice may result in nondeterministic behavior. 不遵循该建议可能导致不确定的行为。

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 );
    }
}

Two things: 两件事情:

  1. Synchronizing on a string you just created does nothing (well, not exactly, since "false" is an interned string, all pieces of code that synchronize on "false" will be synchronized, but that's a hackish way to get application-wide synchronization, and probably not at all what you intended). 在您刚创建的字符串上进行同步不会执行任何操作(嗯,不完全是,因为"false"是一个内部字符串,所有在"false"进行同步的代码段都将被同步,但这是获得应用程序范围内同步的一种不可靠的方式,可能根本没有您的意图)。 You should be synchronizing on the list. 您应该在列表上进行同步。 Everyone using the list should be synchronizing on the list. 使用列表的每个人都应该在列表上进行同步。 Although better practice would be to use a synchronized collection in the first place, eliminating the need for an explicit synchronized block in the using code. 尽管更好的做法是首先使用同步集合,但在使用代码中无需显式synchronized块。
  2. removeAll is usually the most efficient method to remove all occurrences of one or more objects from a collection. removeAll通常是从集合中删除所有出现的一个或多个对象的最有效方法。 In the worst case it is equivalent to iterating over the collection and using the iterator to remove the items (which is the case of LinkedList ), but for some implementations (like ArrayList ) it is made to be more efficient. 在最坏的情况下,这等效于遍历集合并使用迭代器删除项目(在LinkedList的情况下),但是对于某些实现(例如ArrayList ),这样做使其效率更高。

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

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