将值附加到可迭代

时间:2019-03-01 05:41:19

标签: java iterator

说我有一个Iterable<T> iter,并说我有一个想以某种方式加入Iterable的Object v

我发现这似乎是错误的:

var x = List.of(iter);
x.add(v);
return x.iterator();

以上操作无效,因为它希望我改为执行此操作:

 var x = List.of(iter);
 x.add((Iterable<T>)v);
 return x.iterator();

为什么不允许我这样做?:

 var x = List.of(iter);
 x.add((T)v);   // does not compile, expects Iterable<T> not T
 return x.iterator();

我一定做错了..我该如何假装成Iterable?

2 个答案:

答案 0 :(得分:1)

他不允许您这样做:

var x = List.of(iter);
x.add((Iterable<T>)v);
return x.iterator();

因为我认为List x包含(Iterable)类型的对象,所以有必要将要添加到此List的Object强制转换为(Iterable)

答案 1 :(得分:1)

之所以无法进行编译,是因为您最终得到以下内容(未使用var,因此类型很容易看到)。

List<Iterable<T>> x = List.of(iter); // List of Iterable<T> with a single element: "iter"
x.add(v); // Won't compile because "v" is an Object, not an Iterable<T>

x.add((Iterable<T>) v); // Compiles with warnings, will probably fail with ClassCastException at runtime

x.add((T) v); // Won't compile, "v" is being cast to "T" which is not an Iterable<T>

尽管如此,List.of工厂方法返回的是不可修改 List。即使可以编译,最终也会在运行时抛出UnsupportedOperationException


Iterable接口不提供任何用于添加元素的API,仅通过Iterator删除元素(如果实现支持)。这意味着您通常不能在Iterable之前添加元素。如果您需要提供Iterable的API,则可以向其中添加元素,而不应该首先返回Iterable。最好返回Collection,或者,由于需要添加元素,所以最好返回ListDeque。请注意,上述替代方案均从Iterable接口扩展:

  • 可迭代
    • 收藏
      • 列表
      • 设置
      • 队列
        • 双曲

如果由于某种原因必须返回Iterable,或者问题出在第三方API上,那么最好的选择是创建一个副本并将元素添加到副本中。

Iterable<T> iter = ...;
Object v = ...;
List<Object> copy = new ArrayList<>();
copy.add(v); // add v first
iter.forEach(copy::add); // add rest of iterable after v

请注意,List现在是Object的列表。您指定要添加Iterable的{​​{1}}中的T。没有更多信息,这两种类型的共同祖先是Object

如果您不想要副本,并且知道Object的实现类似于可修改 Iterable,则可以进行强制转换然后添加:

List

但是,您拥有((List<T>) iter).add(0, v); // in this case "v" must be of type "T" 的事实表明产生该API的API既不希望也不希望您被该API的使用者修改。