Java 为什么没有一个LinkedList.join()方法可以在O(1)时间内合并两个未排序的列表?

Java 为什么没有一个LinkedList.join()方法可以在O(1)时间内合并两个未排序的列表?,java,collections,linked-list,doubly-linked-list,Java,Collections,Linked List,Doubly Linked List,我不是数据结构专家,但据我所知,链表在大多数情况下效率都很低,主要原因是缓存未命中。我很少考虑使用它们的几个原因之一是在特定的时间内合并/拆分其中两个的独特能力;但是该类没有提供这样的方法 我想,好吧,我会实现我自己的,以满足我的需要。我希望新类遵循Collections框架API,因此我让它实现并扩展了标准LinkedList所实现的类。很快我意识到我只是在重新创建LinkedList,所有这些都是毫无意义的。在这一点上,我可能只是复制粘贴代码并添加所需的方法 同样,我也找不到为什么没有这样一

我不是数据结构专家,但据我所知,链表在大多数情况下效率都很低,主要原因是缓存未命中。我很少考虑使用它们的几个原因之一是在特定的时间内合并/拆分其中两个的独特能力;但是该类没有提供这样的方法

我想,好吧,我会实现我自己的,以满足我的需要。我希望新类遵循Collections框架API,因此我让它实现并扩展了标准LinkedList所实现的类。很快我意识到我只是在重新创建LinkedList,所有这些都是毫无意义的。在这一点上,我可能只是复制粘贴代码并添加所需的方法

同样,我也找不到为什么没有这样一种方法的原因(也许除了线程安全之外,我还远远没有完全掌握线程安全)。一切看起来都像是一个标准的链表实现,一个类似于C++STL中的
splice()
的方法可以在这里使用

我错过什么了吗

LinkedList<Integer> list1 = new LinkedList();
list1.add(4); 
list1.add(2);
list1.add(7);
// list1 = {4 , 2 , 7}

LinkedList<Integer> list2 = new LinkedList();
list2.add(9);
list2.add(4);
list2.add(6);
// list2 = {9 , 4 , 6}

list1.join(list2); // in O(1)
// at this point list2 should be invalidated/empty
// list1 = {4 , 2 , 7 , 9 , 4 , 6}
// list2 = {}
LinkedList list1=新建LinkedList();
清单1.添加(4);
清单1.添加(2);
清单1.添加(7);
//列表1={4,2,7}
LinkedList list2=新建LinkedList();
清单2.添加(9);
清单2.添加(4);
清单2.添加(6);
//列表2={9,4,6}
列表1.加入(列表2);//在O(1)中
//此时,列表2应无效/为空
//列表1={4,2,7,9,4,6}
//列表2={}

Java对本机linkedlist的实现存在问题。没有办法在列表中或列表之间移动节点,不等同于C++ STD::List::SPLICE()。如果在链接列表的任何位置插入或删除节点,则链接列表的所有迭代器都将失效,除非插入或删除是使用迭代器参数完成的,在这种情况下,除了用于插入或删除的迭代器之外,所有迭代器都将失效。迭代器不能被浅层复制,赋值只是将目标迭代器指向源迭代器指向的相同迭代器对象

这些问题使得诸如合并或合并排序之类的操作变得困难,对于基于迭代器的操作来说更是如此

在VisualStudioC++ + STD::列表中,节点的删除只会使迭代器失效到已删除节点,并且仅在调试生成中无效。在发布版本中,迭代器不会失效,由程序员来确保删除的节点不会导致迭代器指向删除的对象


为什么java的本地链接列表有这些限制,Sun在当时的理由是他们想要一个“紧凑的框架”而不是与C++相一致,它比Java集合早4年。(1998为java集合,1994个HP版权日期显示在大多数或所有STL包含在Visual Studio 2005和以前版本的微软和C++ C++编译器中的文件中)。尽管这一事实,集合的前辈JGL确实有一个与C++.P/P>一致的目标。


对Java还有其他批评,比如没有无符号整数,对原语和对象的处理方式不同,对原语的操作集有限,

效率高于一切?绝对不是。可读性和可用性至少同样重要,尤其是对Java而言。而且您描述的操作甚至没有那么频繁正如你所认为的那样(用“错误”的方法可能没有你想象的那么慢)。我也不知道你说的哈希表是什么意思。请注意,即使是
LinkedList
的作者也不使用它()…您在
LinkedList
中发现了利用链表优势的方法吗?没错。更改头部不是主要优势,任何其他不在头部或尾部的更新都需要O(n)遍历。更糟糕的是,列表迭代器可以记住对O(1)节点的引用当通过不同的迭代器进行结构更改时,插入或删除将无效。因此,维护两个或多个列表迭代器以将元素从一个位置传输到另一个位置而不进行遍历是行不通的。并且没有针对任何O(1)的专用API链接操作。@ FVALAIADAD——正如您所评论的,您可以使用替代节点的引用来创建自己的单或双链表的实现,并且几乎重复c++STD::列表功能。我会说, Link KeListList/C++ >更多的是概念证明,证明它有可能实现<代码>列表与
数组列表
不同(在JDK 1.2的集合API之前,只有基于数组的
向量
)。作者的观点说明了这一切……我不知道这是如何回答为什么的问题。@JoachimSauer-我更新了我的答案,将Sun的选择包括在内,但我质疑是否有“紧凑的框架”是放弃功能的有效理由,尤其是当一个预收集实现JGL的目标是与C++和STL一致时。