我正在研究Immutable
收藏品的工厂方法。
我看到Set.of()
方法有10个varargs重载(Map.of()
相同)。我真的无法理解为什么会这么多。最后,无论如何都会调用函数ImmutableCollections.SetN<>(elements)
。
在文档中我发现了这个:
虽然这会在API中引入一些混乱,但它避免了varargs调用引起的数组分配,初始化和垃圾收集开销。
杂乱的确是否值得获得性能提升?如果是,理想情况下是否会为任何N
元素创建单独的方法?
答案 0 :(得分:11)
目前无论如何调用该方法 - 这可能会改变。例如,它可能会创建一个只有三个元素的Set
,依此类推。
并非所有委托给SetN
- 具有零,一和二元素的元素具有ImmutableCollections.Set0
,ImmutableCollections.Set1
和{的实际类别{1}}
或您可以阅读有关此问题的实际问题... here在该问题中阅读ImmutableCollections.Set2
中的评论 - 因为他是创建这些收藏集的人。
答案 1 :(得分:10)
这方面的某些方面可能是未来证明的一种形式。
如果你发展了一个API,你需要注意方法签名将如何改变,所以如果我们有
public class API {
public static final <T> Set<T> of(T... elements) { ... }
}
我们可以说varargs足够好了...除了varargs 强制分配一个对象数组,这虽然相当便宜,但确实影响了性能。例如,参见this microbenchmark,当切换到varargs表单时,显示无操作日志记录的吞吐量损失50%(即日志级别低于loggable)。
好的,我们做了一些分析并说最常见的情况是单身,所以我们决定重构...
public class API {
public static final <T> Set<T> of(T first) { ... }
public static final <T> Set<T> of(T first, T... others) { ... }
}
Ooops ...它不是二进制兼容的...它的源兼容,但不兼容二进制...保留二进制兼容性,我们需要保留以前的签名,例如
public class API {
public static final <T> Set<T> of(T first) { ... }
@Deprecated public static final <T> Set<T> of(T... elements) { ... }
public static final <T> Set<T> of(T first, T... others) { ... }
}
呃...... IDE代码完成现在一团糟......再加上如何创建一组数组? (如果我使用列表可能更相关)API.of(new Object[0])
是不明确的......如果我们没有在开始时添加vararg ...
所以我认为他们所做的是添加足够的显式args以达到额外堆栈大小满足vararg创建成本的程度,这可能是大约10个参数(至少基于Log4J2在添加varargs时所做的测量)到版本2 API)...但是你这样做是为了证明基于证据的未来......
换句话说,我们可以欺骗所有我们没有证据需要专门实施的案例,只是落入vararg变体:
public class API {
private static final <T> Set<T> internalOf(T... elements) { ... }
public static final <T> Set<T> of(T first) { return internalOf(first); }
public static final <T> Set<T> of(T first, T second) { return internalOf(first, second); }
...
public static final <T> Set<T> of(T t1, T t2, T t3, T t4, T t5, T... rest) { ... }
}
然后我们可以分析和查看现实世界的使用模式,如果我们看到重要的使用情况,直到4个arg形式和基准显示有合理的性能增益,那么在那时,在幕后,我们改变了方法impl,每个人都获胜......不需要重新编译
答案 2 :(得分:2)
我想这取决于您正在使用的API的范围。在谈论那些不可变类时,你正在谈论作为jdk的一部分包含的东西;所以范围很广。
所以你有:
如果你正在实现自己的东西,我不会那么关心(但要对varargs参数保持谨慎),除非你真的需要担心那些额外的位(和额外的性能etcetc)。