我想用Iterable初始化Java中的Set Implementation(HashSet).但是,HashSet的构造函数不接受Iterables,而只接受Collections类型的对象.
有没有办法从Iterable转换为某些子集类型.
Con*_*vey 46
你可以使用番石榴.
Set<T> set = Sets.newHashSet(iterable);
Run Code Online (Sandbox Code Playgroud)
或者使它像一个句子静态导入一样读,
import static com.google.common.collect.Sets.*;
Set<T> set = newHashSet(iterable);
Run Code Online (Sandbox Code Playgroud)
当然,它在这个答案中显示出来.基本上,遍历iterable并将其内容复制到集合中:
public static <T> List<T> copyIterable(Iterable<T> iterable) {
Iterator<T> iter = iterable.iterator();
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Run Code Online (Sandbox Code Playgroud)
使用如下,生成的List
对象可以作为参数传递给HashSet
构造函数.
Iterable<Integer> list = Arrays.asList(1, 2, 3);
List<Integer> copy = copyIterable(list);
Set<Integer> aSet = new HashSet<Integer>(copy);
Run Code Online (Sandbox Code Playgroud)
编辑
我一直都弄错了.Iterable
是一个超级接口Collection
,所以一个简单的(但不安全的)演员会做的伎俩,只要Iterable
是一个Collection
开始.
Iterable<Integer> list = Arrays.asList(1, 2, 3);
Set<Integer> aSet = new HashSet<Integer>((Collection)list); // it works!
Run Code Online (Sandbox Code Playgroud)
HashSet
构造函数依赖的不仅仅是Iterable
提供:它想要预先了解size
集合,以便最佳地构建底层HashMap
.如果你有一个真实的,严肃的Iterable
,不知道它的大小,那么你必须Iterable
通过Collection
在任何一些明显的方式中将它变成常规来实现前期.
另一方面,如果你有一个已经知道它的大小的更丰富的对象,那么创建一个将你包装Iterable
成一个集合的简约适配器类是有用的size
,除了转发调用之外还要实现iterator
.
public class IterableCollection<T> implements Collection<T>
{
private final Iterable<T> iterable;
public IterableCollection(Iterable<T> it) { this.iterable = it; }
@Override public Iterator<T> iterator() { return iterable.iterator(); }
@Override public int size() { return ... custom code to determine size ... }
@Override .... all others ... { throw new UnsupportedOperationException(); }
}
Run Code Online (Sandbox Code Playgroud)