我没有找到这个具体问题的直接答案,所以...假设上课:
class MyClass {
private final Set<String> tags;
MyClass(Set<String> initialTags) {
this.tags = ???(initialtags);
}
}
我只想要一个副本而不关心集合的确切实现,只需要很少的开销,所以基本上是内部状态initialTags的直接副本。我不能使用clone
,因为Set是接口。这是可能的,还是我必须使用类似new HashSet<String>(tags);
的东西,需要对类型做出决定?
假设:设置项目类型被resticted为immutable。我可以信任调用者不传递一个损坏的initialTags
Set实现,我相信它可以为这个类中的任何内部用途提供足够好的性能。
我正在考虑尝试反射和克隆(),但这看起来有点脏......
答案 0 :(得分:4)
Guava提供了一种方法:
/**
* Returns an immutable set containing the given elements, in order. Repeated
* occurrences of an element (according to {@link Object#equals}) after the
* first are ignored. This method iterates over {@code elements} at most once.
*
* <p>Note that if {@code s} is a {@code Set<String>}, then {@code
* ImmutableSet.copyOf(s)} returns an {@code ImmutableSet<String>} containing
* each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns
* a {@code ImmutableSet<Set<String>>} containing one element (the given set
* itself).
*
* <p>Despite the method name, this method attempts to avoid actually copying
* the data when it is safe to do so. The exact circumstances under which a
* copy will or will not be performed are undocumented and subject to change.
*
* @throws NullPointerException if any of {@code elements} is null
*/
public static <E> ImmutableSet<E> copyOf(Iterable<? extends E> elements) {
return (elements instanceof Collection)
? copyOf(Collections2.cast(elements))
: copyOf(elements.iterator());
}
答案 1 :(得分:1)
根据initialTags的预期大小,您可能更喜欢不同的实现;下面的代码显示了i is < 100000
时基于构造函数的副本的更快时间,但是i > 1000000
时克隆速度更快。如果你真的想使用clone
,你总是可以使用isinstance
来确定(6)众所周知的具体实现(实现cloneable
)中的哪一个,除此之外你无法保证initialTags
有它。
static Set<String> byCloning(HashSet<String> initialTags) {
return (Set<String>) initialTags.clone();
}
static Set<String> byConstructor(Set<String> initialTags) {
return new HashSet<String>(initialTags);
}
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
HashSet<String> mySet = new HashSet<String>();
for (int n = 0 ; n < N ; n++) mySet.add(Integer.toString(n));
long start = System.currentTimeMillis();
byCloning(mySet);
long end = System.currentTimeMillis();
System.out.println(" time take in milli seconds for cloning = " + (end-start) );
start = System.currentTimeMillis();
byConstructor(mySet);
end = System.currentTimeMillis();
System.out.println(" time take in milli seconds by constructor = " + (end-start) );
}
答案 2 :(得分:0)
根据您需要的访问类型对类型做出决定,或者您可以尝试使用Collections.unmodifiableSet():
class MyClass {
private final Set<String> tags;
MyClass(Set<String> initialTags) {
this.tags = Collections.unmodifiableSet(initialTags);
}
}