Java中的链表有快速连接方法吗?

时间:2010-03-22 16:39:27

标签: java collections linked-list apache-commons guava

如何通过jdk1.6,google或apache commons集合或其他任何方式将O(1)中的两个链表与Java连接起来?例如。在jdk中只有addAll方法,即O(n)。

我想念的另一个功能是连接两个列表,其中每个列表的顺序可能相反。为了说明这一点,假设两个列表a-> b-> c和e-> f-> g可以合并到

  1. a-> b-> c-> e-> f-> g
  2. a-> b-> c-> g-> f-> e
  3. c-> b-> a-> e-> f-> g
  4. C-> B-> A-> G-> F-&GT,E
  5. 您知道这样的列表实现还是我必须实现自己的链表?了解如何调整现有解决方案也很有帮助(例如,jdk LinkedList只有很多私有方法)。这些特征在我看来非常明显,希望我不会错过一些愚蠢的东西。

    正如MicSim所指出的那样,问题Merge two lists in constant time in Java是相关的,但不是真正的重复! 现在的问题是:

    1. 是否可以使用其他集合库?
    2. 如何连续反转?

6 个答案:

答案 0 :(得分:6)

如果您愿意接受Iterable结果,可以使用google-collections Iterables.concat和Iterables.reverse

http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Iterables.html

public static <T> Iterable<T> concat(Iterable<? extends T> a,
                                 Iterable<? extends T> b)

public static <T> Iterable<T> concat(Iterable<? extends T> a,
                                 Iterable<? extends T> b,
                                 Iterable<? extends T> c)

public static <T> Iterable<T> concat(Iterable<? extends T> a,
                                 Iterable<? extends T> b,
                                 Iterable<? extends T> c,
                                 Iterable<? extends T> d)

public static <T> Iterable<T> concat(Iterable<? extends T>... inputs)

public static <T> Iterable<T> concat(Iterable<? extends Iterable<? extends T>> inputs)

答案 1 :(得分:2)

我目前看到的唯一解决方案是实现List,制作如下的构造函数:

public EnhancedList (List l1, List l2)

并覆盖所有方法。在这种解决方案中,您是否想要连接LinkedLists或任何其他列表实际上并不重要。

答案 2 :(得分:0)

我认为使用任何类型的基本列表构造都不会太困难,因为在链接列表中的列表的中间或末尾插入是O(1)。

答案 3 :(得分:0)

调整LinkedList以获得jdk中的O(1)concat将在以下情况下起作用:

  1. 方法entry()以及变量header和size以及内部类Entry将受到保护
  2. addAll会检测LinkedList然后做某事。像:

    JdkLinkedList secondList = (JdkLinkedList) secondColl;
    int numNew = secondList.size();
    if (numNew == 0)  return false;
    modCount++;
    Entry<E> successor = (index == size ? header : entry(index));
    Entry<E> predecessor = successor.previous;
    // TODO LATER if reverse
    
    // connect the last element of this list with the first element of the second list
    // linked list is implemented as a 'cycle' => header.next == first element of second list
    Entry<E> first = secondList.header.next;
    predecessor.next = first;
    first.previous = predecessor;
    
    // append the last element of the second list with the rest of this list
    Entry<E> last = secondList.header;
    successor.previous = last;
    last.next = successor;
    

答案 4 :(得分:0)

对于concat我建议你做以下事情:

  • 确保所有参数/变量都声明为List&lt; ...&gt;不是LinkedList&lt; ...&gt;
  • 更改新的LinkedList&lt; ...&gt;();到新的ArrayList&lt; ...&gt;();
  • 描述应用程序
  • 更改新的ArrayList&lt; ...&gt;到新的LinkedList&lt; ...&gt;();
  • 描述应用程序

根据您的使用情况,ArrayList可能比LinkedList快得多。另外,通过查看配置文件数据,您可以看到使用addAll可以获得多少性能 - 如果它不是那么大,则不需要“修复”它。

对于某些事情,您使用其他语言的经验不会成立。您可能会发现addAll满足您在Java中的要求。

如果您要编写自己的可查询列表,请确保它符合List接口,然后更改您的代码并重新配置它并确保它更快。如果不是那么扔掉它并坚持使用标准的List类型。

答案 5 :(得分:0)

FastList from javolution不是一个开箱即用的解决方案,但尾部()和头部()非常接近我的最爱。

我认为trove是解决方案,尽管在O(1)中没有方便的方法用于反转或addAll。