如何从 Java 集合中获取相同的输出顺序

How to get the same output order from a Java Collection

我有一些代码:

Collection<MyGraph.MyVertex> vertCollection = graph.getVertices(); 

其中 getVertices 是 JUNG 包的一部分,定义如下:

public interface Hypergraph<V, E> {
    Collection<E> getEdges();

    Collection<V> getVertices();
...
...
}

> If I print out the collection I may get something like [v1,v2,v4,v3]
> and on another run something like [v2,v3,v1,v4]

这每次都会返回一个随机顺序的顶点列表。因此,我在代码其他地方的结果不可重复,而且很难追踪。

我想每次都以相同的方式恢复元素的顺序。我目前的猜测是我必须将集合转换为某种保留顺序的数据结构,然后对其进行排序,以便结果是可重复的,但是有没有更好的方法来做到这一点? (我不确定从 Collection 转换为数组等其他东西是否会破坏其他地方的代码,因为我是 Collections 的新手)。任何帮助都会很棒!

你可以使用这样的东西:

List<String> names = Arrays.asList("Alex", "Charles", "Brian", "David");

//Natural order
Collections.sort(names);    //[Alex, Brian, Charles, David]

//Reverse order
Collections.sort(names, Collections.reverseOrder());    [David, Charles, Brian, Alex]   

只需使用ArrayList 来实现Collection。 ArrayList 的行为就像一个数组。它们以相同的顺序出现。

Collection<E> list = new ArrayList<>();
Collection<V> list = new ArrayList<>();

我了解到 Hypergraph.getVertices() 是您无法修改的库方法。所以你必须操纵调用该方法的结果。正如 .

所建议的,排序是此处的选项

但这需要您实现 <V>(示例中的 MyGraph.MyVertex)将实现 java.lang.Comparable,或者您提供 java.util.Comparator 的实现以确保顶点的静态排序顺序。

java.util.Collections.sort()接受一个List作为参数; List 的实例也始终是 Collection 的实例,但不幸的是,并非 Collection 的每个实例都是 List 的实例 – 它可能是 Set 甚至是一些绝对奇怪的东西……

考虑到这一点,并假设 VertComparator 是我谈到的比较器,您的解决方案可能如下所示:

…
VertComparator comparator = new VertComparator();
List<MyGraph.MyVertex> vertCollection = new ArrayList<>( graph.getVertices() );
Collections.sort( vertCollection, comparator );
…

如果您程序中的所有其他代码只处理 Collection 个顶点实例(这意味着在某处没有隐藏假设它是什么类型的集合),您应该是安全的。

不幸的是,即使返回的 Collection 已经是 List 的实例(… instanceof List 产生 true),Collections.sort() 也可能不起作用:使用 List.of() 并尝试对其进行排序......

通常,当一个方法 returns 一个 Collection 以某种方式表示对象的内部状态时,这是一个不可修改的集合。显然,这里的排序也会失败。所以唯一安全的方法就是复制结果,然后对副本进行排序。

如您所见,JUNG 2.x 本身不提供此选项,因此您唯一真正的选择是复制输出并对其进行排序,并且假设您有一个 Comparator 这对您的顶点类型有意义。 (这也使得保留原始插入顺序变得容易。)

Guava graph library, also known as common.graph, is used by JUNG 3.0(开发中)并在几个不同的层面上支持稳定排序:

  1. Immutable graphs' 访问器每个 return 具有稳定排序的 Set

  2. 如果你想要一个mutable graph, the built-in implementations, which are constructed using GraphBuilder (and its sibling types) can specify using nodeOrder()图形节点应该是以下任何一个:

    • 按插入顺序(默认)
    • 无序
    • 自然排序(如果您的节点类型实现 Comparable
    • 已排序

    对于 Networks(类似于 JUNG Graph 类型),您可以对图的边施加相同的排序。

  3. 您还可以构造一个可变图,它使用 incidentEdgeOrder() 在图上 Builder.

(免责声明:我共同创建了 JUNG 并仍在维护它,还创建了 common.graph。)