将番石榴集转换为列表的最快方法

Fastest way to convert Guava Sets to List

我什至不确定这是否可行,但我正在执行 unionintersection 之类的 Set 操作,我需要将其转换为 List 以便打乱列表并将其传递给接受 List 而不是 Set 的不同方法。所以我将结果转换为 List 并且一切都很好。但是然后从探查器中,我看到该操作在负载下花费了很长时间,这是因为 Guava Sets .size() 的方式。这不是像正常 java Set.

那样的常量操作

这是代码示例

    @Test
    void testSet() {
        Set<Character> first = ImmutableSet.of('a', 'b', 'c');
        Set<Character> second = ImmutableSet.of('b', 'c', 'd');

        Set<Character> union = Sets.union(first, second);

        List<Character> characters = new ArrayList<>(union);
    }

我正在尝试找到将 Guava Sets 转换为 List 的最快方法。通过深入挖掘代码,这就是 Guava Sets 所做的 https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/Sets.java#L694。这不是一个持续的操作,它会损害高负载下的性能。我猜 .size 调用是从 Java 想要将新集合复制到新列表时开始的,它必须知道创建列表的大小。

将“高负载下的性能”参数放在一边(如果它确实与您的用例相关,我建议进行适当的 JMH 微基准测试),Sets 操作是内存优化的,所以如果您要复制数据马上,您可能想尝试完全不调用大小的不同方法。

首先,Sets.union returns SetView<E> which has immutableCopy(),然后你可以调用 .asList() 视图,返回一个不可变列表(随意将所有操作链接在一起):

@Test
public void testSetCopy() {
    Set<Character> first = ImmutableSet.of('a', 'b', 'c');
    Set<Character> second = ImmutableSet.of('b', 'c', 'd');

    Sets.SetView<Character> union = Sets.union(first, second);
    List<Character> characters = union.immutableCopy().asList();

    assertThat(characters).containsOnly('a', 'b', 'c', 'd');
}

其次,你也可以考虑首先使用Set,正如Louis所说:

@Test
public void testMultiset() {
    Set<Character> first = ImmutableSet.of('a', 'b', 'c');
    Set<Character> second = ImmutableSet.of('b', 'c', 'd');

    // here it's ugly but maybe you can collect to set in the first place
    ImmutableMultiset<Character> set = ImmutableSet.<Character>builder()
             .addAll(first)
             .addAll(second)
             .build(); // [a, b, c, d]

    List<Character> characters = set.asList();

    assertThat(characters).containsOnly('a', 'b', 'c', 'd');
}

也就是说,YMMV,我再次鼓励您在选择任何可读性较差的选项之前进行微基准测试。