Java在O(1)中合并2个集合

Java在O(1)中合并2个集合,java,algorithm,collections,merge,Java,Algorithm,Collections,Merge,我需要能够将2个大型集合合并为1个。我可以最好地使用哪种收集类型?我不需要随机访问单个元素。通常我会选择linkedlist,但是我不能将Java中的2个linkedlist与O(1)的运行时合并,这可以在许多其他语言中完成,因为我必须将每个元素复制到新列表中 编辑:谢谢你的回答。你的回答都很有帮助,我成功地完成了工作。下次我将使用我自己的链表实现开始 理论上,您可以在O(1)中合并两个链表,因为您所要做的就是将第一个链表的最后一个节点指向第二个链表的第一个节点(假设您有这些引用) 集合的add

我需要能够将2个大型集合合并为1个。我可以最好地使用哪种收集类型?我不需要随机访问单个元素。通常我会选择linkedlist,但是我不能将Java中的2个linkedlist与O(1)的运行时合并,这可以在许多其他语言中完成,因为我必须将每个元素复制到新列表中


编辑:谢谢你的回答。你的回答都很有帮助,我成功地完成了工作。下次我将使用我自己的链表实现开始

理论上,您可以在O(1)中合并两个链表,因为您所要做的就是将第一个链表的最后一个节点指向第二个链表的第一个节点(假设您有这些引用)

集合的
addAll
方法似乎意味着运行时间为O(n),因为它们讨论的是迭代器。详细信息可能是特定于JVM的


我不认为有任何集合会在O(n)中合并。您可能需要自己动手。

这里最简单的解决方案实际上是一个列表列表。这意味着您需要一些简单的包装函数,但并不复杂。

我认为最好是创建一个List的实现,该实现将List>作为其参数,然后委托。换句话说,创建一个列表列表,并将它们连接起来作为一个列表。当您经过列表1的元素时,您将开始查看列表2


出于某种原因,我认为番石榴有这样一个清单。但是在JavaDOCs中找不到它。

合并链表确实是O(1),并且可以以相同的方式考虑基于数组的列表,即在[./p>之间有多个对象]链接。 上面有一些实现,当从中间/开始删除/插入时,它比ArrayList快。


迭代实际上是一样的。不过,随机访问可能会稍微慢一些。

您可以使用的方法之一在O(1)中创建一个串联的
Iterable
视图:

Iterable combined=Iterables.concat(列表1、列表2);
这将允许您将两个列表的所有元素作为一个对象进行迭代,而无需复制任何元素。

我想建议使用apache.commons中的类,但也可以查看在O(n)中运行的This。 如果您只需要迭代元素,而不想使用ColinD建议的Google集合,那么您可以轻松创建自己的复合迭代器,例如

public class CompositeCollectionIterator<T> implements Iterator<T>{

  private Iterator<T>[] iterators;
  private int currentIteratorIndex = 0;
  public CompositeCollectionIterator( Collection<T>... aCollections ) {
    iterators = new Iterator[ aCollections.length];
    for ( int i = 0, aCollectionsLength = aCollections.length; i < aCollectionsLength; i++ ) {
      Collection<T> collection = aCollections[ i ];
      iterators[i] = collection.iterator();
    }
  }

  public boolean hasNext() {
    if ( iterators[currentIteratorIndex].hasNext() ) return true;
    else if ( currentIteratorIndex < iterators.length - 1 ){
      currentIteratorIndex++;
      return hasNext();
    }
    return false;
  }

  public T next() {
    return iterators[currentIteratorIndex].next();
  }

  public void remove() {
    iterators[currentIteratorIndex].remove();
  }
}
公共类CompositeCollectionIterator实现迭代器{
私有迭代器[]迭代器;
私有int currentIteratorIndex=0;
公共CompositeCollectionIterator(集合…集合){
迭代器=新迭代器[aCollections.length];
for(int i=0,aCollectionsLength=aCollections.length;i
如果您只想拥有对象集合并在O(1)时间内合并它们,并且不介意实现自己的数据结构,那么最简单的方法就是使用一个不平衡的二叉树:每个节点要么是一个叶(存储一个值),要么是两棵树的组合,您可以将它们实现为两个带有抽象超类或接口的类。深度优先遍历可用于提取元素

这本质上与ColinD关于迭代器连接的建议相同,但更简单

需要注意的是,迭代这个集合将而不是成为O(n)!它将是O(n+m),其中m是已执行的合并数(因为每个合并都是要遍历的节点)。我的解决方案和科林的都是这样。我不知道这是否适用于这个问题的所有可能的解决方案


别管上面的事。在该方案下,每次合并至少增加一个元素,因此m使用两个链接列表作为集合,并存储指向每个列表的第一个和最后一个元素的指针(添加/删除项时可能需要更新这两个指针),您可以在O(1)中合并两个列表-只需将第一个列表的最后一个元素连接到第二个列表的第一个元素,并相应地调整第一个/最后一个指针

恐怕您需要在Java中推出自己的链表实现,因为您无法直接访问
LinkedList
的底层节点,因此无法将第一个列表的最后一个元素连接到第二个列表的第一个元素


幸运的是,在Java中很容易找到链表实现,因为它是数据结构课程中非常常见的主题。例如,是一个-我知道,名称是西班牙语的,但是
listaencadenda
(“LinkedList”)和
NodoLista
(“ListNode”)中的代码非常简单,应该是自解释的,最重要的是-实现包含指向列表的第一个和最后一个元素的指针,并且可以轻松修改以满足您的需要。

我认为问题在于如何在Java中实现这一点。因此,他可以像处理任何其他集合一样处理最终结果,而无需创建自己的类+1对于这个问题,btwI知道,但正如Jan所说,我想知道这在Java本身是否已经可行。最后一个假设在Java中是否真的成立?@hvgotcodes addAll方法必须复制节点,否则对源列表的修改将可见
public class CompositeCollectionIterator<T> implements Iterator<T>{

  private Iterator<T>[] iterators;
  private int currentIteratorIndex = 0;
  public CompositeCollectionIterator( Collection<T>... aCollections ) {
    iterators = new Iterator[ aCollections.length];
    for ( int i = 0, aCollectionsLength = aCollections.length; i < aCollectionsLength; i++ ) {
      Collection<T> collection = aCollections[ i ];
      iterators[i] = collection.iterator();
    }
  }

  public boolean hasNext() {
    if ( iterators[currentIteratorIndex].hasNext() ) return true;
    else if ( currentIteratorIndex < iterators.length - 1 ){
      currentIteratorIndex++;
      return hasNext();
    }
    return false;
  }

  public T next() {
    return iterators[currentIteratorIndex].next();
  }

  public void remove() {
    iterators[currentIteratorIndex].remove();
  }
}