使用Iterable初始化Set

时间:2013-05-08 20:44:04

标签: java set

我想用Iterable初始化Java中的Set Implementation(HashSet)。但是,HashSet的构造函数不接受Iterables,而只接受Collections类型的对象。

有没有办法将Iterable转换为某些子集类型。

7 个答案:

答案 0 :(得分:44)

您可以使用Guava

Set<T> set = Sets.newHashSet(iterable);

或使其读起来像句子静态导入,

import static com.google.common.collect.Sets.*;

Set<T> set = newHashSet(iterable);

答案 1 :(得分:7)

当然,它显示在this答案中。基本上,遍历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;
}

如下所示使用它,生成的List对象可以作为参数传递给HashSet构造函数。

Iterable<Integer> list = Arrays.asList(1, 2, 3);
List<Integer> copy = copyIterable(list);
Set<Integer> aSet = new HashSet<Integer>(copy);

修改

我一直都弄错了。 IterableCollection的超接口,所以只要Iterable开始为Collection,一个简单(但不安全)的演员就可以完成这项工作。

Iterable<Integer> list = Arrays.asList(1, 2, 3);
Set<Integer> aSet = new HashSet<Integer>((Collection)list); // it works!

答案 2 :(得分:6)

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(); }
}

答案 3 :(得分:3)

只需添加每一个。

public static <T> Set<T> setFromIterable(Iterable<T> i) {
    HashSet<T> set = new HashSet<T>();
    Iterator<T> it = i.iterator();
    while (it.hasNext()) {
        set.add(it.next());
    }
    return set;
}

Iterable<Integer> someIterable = ...;
Set<Integer> someSet = setFromIterable(someIterable);

请注意,使用构造函数new HashSet<Integer>(someIterator),因为它不存在。只需调用静态方法。

答案 4 :(得分:0)

Iterable接口允许“foreach”语法工作,因此最简洁的方法可能是:

public <T> Set<T> toSet(Iterable<T> collection) {
    HashSet<T> set = new HashSet<T>();
    for (T item: collection)
        set.add(item);
    return set;
}

答案 5 :(得分:0)

我使用这种单行(使用 Java 8+),它只依赖于 java.util.stream

StreamSupport.stream(myIterable, false).collect(Collectors.toSet());

// or with static imports:
stream(myIterable, false).collect(toSet());

答案 6 :(得分:-1)

为了简洁起见,有些重复的答案。下面为我​​工作将 String 类型的 Iterable 转换为 Set(Java8)。

Iterable<String> stringIterable = Arrays.asList("str1", "str2", "str3");
Set<String> stringHashSet = new HashSet<>((Collection<? extends String>) stringIterable);