9

我的代码中有两个 LinkedList,我需要制作一个两者兼有的。我不再需要这个列表,只需要新的列表,它包含我需要的所有数据。

我可以使用 .addAll(),但性能是我的大问题,我迫不及待地想复制、添加引用,每次都……

如果我们创建自己的链表,我正在寻找我们通常所做的事情,只需将最后一个节点从一个节点连接到第二个节点的第一个节点。有没有办法使用 java api 中的 LinkedList 类来做到这一点?


合并集合是另一种情况,尽管操作的含义几乎相同,但我的问题只是关于性能并且仅针对链表,它通常可以满足我的需要。“合并”也是一个模棱两可的术语,我想要的只是将它们放在一起,无论它们是什么顺序,考虑到性能。我不是在寻找是否可以合并......

另一件事,我的问题只是关于 API,我不是在寻找构建自己的代码(老板要求),这就是为什么与这个不同:在 Java 中以恒定的时间合并两个列表 - 那里也没有有用的答案..

4

7 回答 7

3

如果您只想遍历新列表并且可以替换ListIterable您可以使用 Guava Iterable.concat,如下所述:

将多个集合组合成一个逻辑集合?

于 2013-08-27T15:38:13.157 回答
3

如果您正在使用,LinkedList那么您很可能对索引访问不感兴趣(因为索引访问很慢......但请记住,列表仅存储引用,因此对于很少插入/删除的非常大的列表,您将更多内存效率高,ArrayList因为它不需要在堆上分配每个节点)

所以你真正想要的是能给你大部分List合同的东西……或者甚至不是。

很可能你想要的只是能给你的东西Iterable<String>......如果是这样,那么你的生活就会很轻松:

public class UberIterable<T> implements Iterable<T> {
  private final List<List<T>> lists;
  public UberIterable(List<T>... lists) {
    this.lists = Arrays.asList(lists); 
  }
  public Iterator<T> iterator() {
    return new Iterator<T>() {
      Iterator<List<T>> metaNext = lists.iterator();
      Iterator<T> next;
      public boolean hasNext() {
        while (true) {
          if (next != null && next.hasNext()) return true;
          if (metaNext.hasNext()) next = metaNext.next(); else return false; 
        }
      }
      public T next() {
        if (!hasNext()) throw new NoSuchElementException();
        return next.next();
      }
      public void remove() {
        throw new UnsupportedOperation();
      }
    }
  }
}

这是一个基本实现,它将为您提供许多列表的合并视图。如果你想获得更多的合同,List你可以重复相同的技巧,只有更好的实现ListIterator才能获得很多你可能想要的东西,或者最后通过用你的新实现扩展AbstractList和覆盖适当的方法ListIterator

于 2013-08-27T15:46:27.943 回答
2

恐怕唯一的方法就是使用反射......当你查看源代码时LinkedList,你可以看到子类Entry<E>是私有的,如果你想连接第一个和这是一个问题最后条目到其他条目,以便合并列表。

更新:即使反射也不安全(除非您添加检查),因为Oracle 将子类的名称更改EntryNode并更改了构造函数的参数顺序!在 JDK 7 中,恕我直言,这是愚蠢的。

肮脏的解决方案:对源代码进行完整的复制粘贴并将private关键字更改为public. 但是,我不确定 Oracle 是否允许这样做。检查他们的执照。

于 2013-08-27T14:52:25.153 回答
2

恐怕答案是否定的。使用的内部EntryLinkedList是私有的,所有公开的公共方法都LinkedList与通用集合一起使用。

你的用例对我来说似乎是合理的,但这个实现不支持它。

于 2013-08-27T14:52:36.773 回答
1

为什么不创建一个实现 List 并包含对 2 个子列表的引用的包装器/代理类,然后实现 List 方法(或至少是您需要下游的方法) - 做一些工作,但如果复制其中一个列表确实是问题听起来值得。

于 2013-08-27T15:40:04.617 回答
1

您可以这样做的一种方法是使用getLast()从其中一个列表中获取最后一个元素,然后在另一个上使用addFirst()以将其添加到前面。

然而,正如这里所说,addAll()不会复制任何内容,并且可以很容易地使用。

如果您的问题与 LinkedList 中节点对象的实际实例化有关,您可能需要实现自己的版本,在其 API 中公开更多实现机制。

于 2013-08-27T14:41:39.730 回答
0

导入 java.util.LinkedList;

公共类 MergeLinkedList {

public static void main(String[] args) {

    LinkedList<String> mainlist = new LinkedList<String>() ;

    mainlist.add("A");
    mainlist.add("B");

    LinkedList<String> secondlist = new LinkedList<String>() ;

    secondlist.add("C");
    secondlist.add("D");

    mainlist.addAll(secondlist);
    System.out.println(mainlist);
}

}

O/P [A, B, C, D]

你必须使用 addall();

于 2013-08-27T15:30:03.207 回答