将Iterable<T>转换为T[]的可重复使用方法?

25
我将尝试编写一个通用的方法,以数组形式返回可迭代对象的内容。
以下是我的代码示例:
public class IterableHelp
{
    public <T> T[] toArray(Iterable<T> elements)
    {
        ArrayList<T> arrayElements = new ArrayList<T>();
        for(T element : elements)
        {
            arrayElements.add(element);
        }

        return (T[])arrayElements.toArray();
    }
}

但是我得到了一个编译器警告:“注意:...\IterableHelp.java使用了未经检查或不安全的操作。”

对于避免这样的警告,您有什么其他想法吗?


2
我猜测警告出现在最后一行,你将数组转换为 T[] 的地方? - Tyler
2
还可以查看Guava的Iterables.toArray(Iterable<? ex T>, Class<T>) - Michael Brewer-Davis
3个回答

27

谷歌Guava中有一个名为Iterables.toArray的方法。

通过查看源码,可以看到其定义如下:

  /**
   * Copies an iterable's elements into an array.
   *
   * @param iterable the iterable to copy
   * @param type the type of the elements
   * @return a newly-allocated array into which all the elements of the iterable
   *     have been copied
   */
  public static <T> T[] toArray(Iterable<? extends T> iterable, Class<T> type) {
    Collection<? extends T> collection = toCollection(iterable);
    T[] array = ObjectArrays.newArray(type, collection.size());
    return collection.toArray(array);
  }

ObjectArrays.newArray 最终委托给一个类似以下方法的方法:

  /**
   * Returns a new array of the given length with the specified component type.
   *
   * @param type the component type
   * @param length the length of the new array
   */
  @SuppressWarnings("unchecked")
  static <T> T[] newArray(Class<T> type, int length) {
    return (T[]) Array.newInstance(type, length);
  }

看起来似乎没有办法完全避免使用@SuppressWarnings,但是你至少应该将其限制在最小的范围内。

或者,更好的方法是使用别人的实现!


2

没有一种方法可以消除unchecked or unsafe operations的警告,或者创建一个TypeSafe数组而不编辑您的方法签名。

查看此错误报告以获取详细信息。

一种方法是传入预先分配的类型为T的数组:

public class IterableHelp
{
    public <T> T[] toArray(final T[] t, final Iterable<T> elements)
    {
        int i = 0;
        for (final T element : elements)
        {
            t[i] = element;
        }
        return t;
    }
}

这样可以消除unchecked or unsafe警告,但同时也将责任转移到调用类上,需要正确地创建数组边界,这有点违背了你方便方法的初衷。

如果您想动态创建TypeSafe数组,实际上在Java中无法以TypeSafe方式完成。

这个方法可以工作和编译,但它并没有解决unchecked or unsafe强制转换问题,只是将其移至另一个位置。我不得不添加@SuppressWarnings注释才能停止对强制转换的抱怨。

@SuppressWarnings({"unchecked"})
public class IterableHelp
{
    public <T> T[] toArray(Class<T> t, Iterable<T> elements)
    {
        final ArrayList<T> arrayElements = new ArrayList<T>();
        for (T element : elements)
        {
            arrayElements.add(element);
        }
        final T[] ta = (T[]) Array.newInstance(t, arrayElements.size());
        return arrayElements.toArray(ta);
    }
}

0

你面临的问题比未经检查的警告更大。实际上,如果T不是Object,则会在运行时抛出ClassCastException。

尝试 String[] foo = IterableHelp.toArray(new ArrayList<String>());

简单来说,由于数组在运行时包含组件类型,因此要创建正确的T[],必须将组件类作为另一个参数传递(可以是T或T[]本身的类,也可以是T或T[]的对象),并使用反射创建数组。 CollectiontoArray() 方法的形式需要传入一个T[]对象,就是为了这个原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接