为什么Java Collection Framework不包含Tree和Graph
我熟悉Java Collection Framework,它包含基本接口:Collection
和Map
。我想知道为什么框架不包含树和图等基本集合的结构。两者都可以被视为Collection
的子类型。
顺便说一句,我知道TreeSet
是由红黑树底层实现的。然而,TreeSet
不是一个 Tree,而是一个 Set
,因此框架中没有真正的 Tree。
I am familiar with Java Collection Framework which contains basic interfaces: Collection
and Map
. I am wondering why the Framework doesn't contain structures as Tree and Graph which are basic collections. Both can be regarded as sub types of Collection
.
By the way, I know TreeSet
is implemented by Red-Black Tree underlying. However, the TreeSet
is not a Tree but a Set
, so there's no real Tree in the framework.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这是一个很好的问题。我认为这只是归结为范围界定。 Collections API 提供的类的核心功能包括:
迭代顺序:列表和排序映射具有指定的迭代顺序,大多数集合没有。
重复:列表允许重复,集合不允许
索引 :列表值由整数索引,地图值由其他对象索引。
这让我们走得很远,我认为 Joshua Bloch 等人认为可以在这三个之上实现更多功能丰富的集合(需要元素之间内部关系的图和树、具有多重性的集合、双向映射……)核心功能,因此在图书馆中效果更好。
This is a good question. I think it simply boils down to scoping. The core features that Collections API provides classes for are:
iteration order: Lists and sorted maps have specified iteration order, most sets don't.
duplicates: Lists allow duplicates, sets do not
index: List values are indexed by integers, map values are indexed by other objects.
This gets us very far and I assume Joshua Bloch et al argued that more feature rich collections (graphs and trees which require internal relationship between elements, sets with multiplicity, bi-directional maps, ...) can be implemented on top of these three core features, and are thus better off in libraries.
java.util
包包含用于组织任何类型数据的数据结构。它基本上处理通过其方法和定义的抽象数据结构(如List
、Set
、Map
)行为(例如,Set 两次不包含任何元素,List 保持顺序并允许重复,等等)。作为开发人员,您可以自由选择最适合您处理的数据类型的这些数据结构的实现(HashSet 与 TreeSet / LinkedList 与 ArrayList / 等)。例如,对于集合和映射,您可以在基于散列的实现和基于树的实现之间进行选择,这可能适合也可能不适合您想要做的事情(在大多数情况下,基于散列的实现将是最佳选择,而有时,当顺序很重要时,树可能更适合您的需求 - 另请参阅 HashSet 与 TreeSet(此处位于 Stackoverflow) )。
如果您将树视为一种特殊的图(事实确实如此),那么您对适用于图的特定属性感兴趣,而不是一般的集合(本质上是列表,并且依次使用来实现诸如图表之类的东西)。
正如本线程中提到的,如果您对图形建模感兴趣,那么图形库有很多选择。我个人可以推荐 JGraphT。
我不知道为什么 JDK 中没有图形库(而且我不知道这是否是一件好事?),但我猜 Sun 决定将其留给开发人员,因为大多数需要图形的应用程序也需要非常独特的实现。
The
java.util
package contains data structures to organize data of any kind. It deals basically with abstract data structures (likeList
,Set
,Map
) which are defined via their methods and behavior (e.g. a Set does contain no elements twice, a List maintains order and allows duplicates, etc.).You as a developer are free to choose which implementation of these data structures are best suited for the kind of data you deal with (HashSet vs. TreeSet / LinkedList vs. ArrayList / etc.). For example for Sets and Maps you may choose between hash-based implementations and tree-based implementations, which may or may not be suited for what you want to do (in most cases a hash-based implementation will be the best choice, while sometimes, when order is important, a tree may be better suited for your needs - See also HashSet vs TreeSet (here at Stackoverflow)).
If you are thinking of a Tree as a special kind of Graph (which it is), then you’re interested in specific properties which apply to graphs, not to collections in general (which, essentially, are lists, and are in turn used to implement things like graphs).
As mentioned in this thread, if you’re interested in modeling Graphs, there are plenty of choices for Graph libraries. Personally I can recommend JGraphT.
I don’t know why there is no graph library within the JDK (and I don’t know whether that’s a good thing to ask?), but I guess Sun decided to leave this to developers, since most applications that require graphs also require very unique implementations.
我怀疑答案是它是两件事的组合:
请注意,Apache commons 或 Google commons 都没有通用图或树支持。然而,我确实遇到了一些通用的树/图层次结构:
I suspect that the answer is that it is a combination of two things:
Note that neither Apache commons or Google commons have generic graph or tree support. However, I did come across a couple of generic tree/graph hierarchies:
原始答案
图(更具体地说,树,如您所知,一种特殊情况,只有一个根,不能有循环并且所有节点都连接)的主要问题是,该假设的集合应该保存在另一个结构中:节点。很难制定标准这种处理方式,因为它需要双层“容器”。
如果有人碰巧使用过
JTree
的TreeModel
,就会注意到几乎不可能避免这样一个事实:后面有TreeNode
(内部) ?)并且您必须同时操作节点和树。不管怎样,我同意这个结构是有用的,但是很难使其成为标准,只需注意,例如,Apache Commons Collections
和 Google Guava这两个大的API 的集合扩展,也没有。更新
根据概述API的:
因此,虽然图表是正确的集合,但也许可以使按照标准,由于之前解释过需要双层容器,因此实施的规模和复杂性太大,无法满足此设计目标。
此外,Google Guava 添加了对图表的支持。 Apache 有一个用于图表的沙箱(正在开发中),但自 2011 年以来似乎处于休眠状态。
Original answer
The main problem with graphs (and more concretely trees, as you know, a special case where there's a one only root, there can be no loops and all nodes are connected) is that each item in that supposed collection should be hold in another structure: the node. It's tough to make standard that kind of treatment as it requires a double layer of "containers".
If anyone ever happens to work with the
TreeModel
forJTree
would notice that is almost impossible to avoid the fact that there areTreeNode
s behind (inside?) and you have to manipulate both, nodes and trees.Anyway, I agree that the structure would be useful but it's very hard to make it standard, just notice that, for instance, neither Apache Commons Collections
nor Google Guava, two big collection extensions for the API, don't have them either.Update
According to the overview of the API:
So while graphs are proper collections and it'd be maybe possible to make it standard, the size and complexity of the implementation would be too big to fit this design goal, because of the previously explained need of a double layer of containers.
Also, Google Guava has added support for graphs. Apache had a sandbox (development in progress) for graphs but seems dormant since 2011.
恐怕答案是:设计和维护通用的树结构和接口太麻烦了(参见
I am afraid the answer is: it's too troublesome to design and maintain a generic tree structure and interfaces (see answer to this post). Most users will need the performance of tree-based implementations of lists and sets, but will not be concerned with the internals, so most of them are hidden.
有一个树接口 - javax.swing.tree.TreeModel,它实际上适用于任意有向图(具有显着的“根”节点)。不过,它没有实现
Collection
接口(因为 Swing 比集合框架要老一些,而且目前还不清楚这里是否真的适合作为一个集合)。(TreeModel 的一个实现是
DefaultTreeModel
,它使用从TreeNode
对象构建的树,它本身就是一个可由用户实现的接口。)另一种类型的树由 XML 给出-DOM框架。
一些特定的使用树(或主要是“树节点”)由 java.io.File、java.awt.Component(和子类)、编译器树 API(
com.sun.source.tree.*
)、Doclet API (com.sun.javadoc.*
)、反射 API (java.lang.Class
),语言模型 API (javax.lang.**
)。如果你比较这些API,
问题是,对于树来说,没有明确的通用有用接口——这样的树应该能够做什么?
一棵树只是其他树(低一级的树)的集合,还是只是指向根节点的指针,其中每个节点本身包含更多节点?或者树是所有节点的集合?还是所有节点所有内容的集合?所有节点都必须有“内容”,还是只有叶节点?如果树是一些内容元素(而不是节点本身)的集合,那么迭代器应该如何表现?一棵树有多大?
这是对树节点(或者实际上它可以是通用有向图节点,如果不是父指针)接口的建议:
这对于所有类型的树(例如上面列出的树)来说是否足够?我不这么认为。
There is an interface for trees -
javax.swing.tree.TreeModel
, which in fact works for arbitrary directed graphs (with a distinguished "root" node). It does not implement theCollection
interface, though (since Swing is a bit older than the collection framework, and it is not really clear that being a collection would really be appropriate here).(One implementation of TreeModel is
DefaultTreeModel
, which uses a tree build fromTreeNode
objects, which is itself an interface implementable by users.)Another type of trees are given by the XML-DOM frameworks.
Some specific use trees (or mostly "tree nodes") are defined by
java.io.File
,java.awt.Component
(and subclasses), the Compiler tree API (com.sun.source.tree.*
), the Doclet API (com.sun.javadoc.*
), the Reflection API (java.lang.Class
), the language model API (javax.lang.**
).If you compare these API
The problem is, there is no clear general-purpose useful interface for trees - what should such a tree be able to do?
Is a tree simply a collection of other trees (those one level lower), or simply a pointer to the root node, where each node itself contains more nodes? Or is a tree a collection of all the nodes? Or a collection of all the contents of all the nodes? Do all nodes have to have "content", or only the leaf nodes? If a tree were a collection of some content elements (and not the nodes itself), how should an iterator behave? What would be the size of a tree?
Here is a proposal for a tree node (or in fact it could be a general directed graph node, if not for the parent-pointer) interface:
Would this be enough for all types of trees, for example the ones listed above? I don't think so.