代码之家  ›  专栏  ›  技术社区  ›  Albert

java:如何实现'集合'的'

  •  7
  • Albert  · 技术社区  · 14 年前

    现在,我有:

        public <T> T[] toArray(T[] old) {
            T[] arr = Arrays.copyOf(old, old.length + size());
            int i = old.length;
            for(E obj : this) {
                arr[i] = old.getClass().getComponentType().cast(obj);
                ++i;
            }
            return arr;
        }
    

    (请注意,这不符合AXTAVT指出的合同。)

    当我收到这个警告时:

    Type safety: Unchecked cast from capture#2-of ? to T
    

    这仍然是实现它的最佳/最直接的方法吗?我能在没有警告的情况下用某种方式编码吗?否则我将如何实现它?


    编辑:我当前的解决方案。首先,我真的不想在 toArray 本身。因此,我编写了这些小助手函数( read here 有关这些问题的进一步讨论:

    @SuppressWarnings("unchecked") static <T> Class<? extends T> classOf(T obj) {
        return (Class<? extends T>) obj.getClass();
    }
    
    @SuppressWarnings("unchecked") static <T> Class<? extends T> classOf(T[] array) {
        return (Class<? extends T>) array.getClass().getComponentType();
    }
    
    @SuppressWarnings("unchecked") static <T> T[] newArray(Class<T> clazz, int size) {
        return (T[]) Array.newInstance(clazz, size);
    }   
    

    现在,我的 托拉里 实现方式如下:

        public <T> T[] toArray(T[] array) { 
            int size = size();
            if (array.length < size) { 
                array = newArray(classOf(array), size);
            } else if (array.length > size) {
                array[size] = null;
            }
    
            int i = 0;
            for (E e : this) {
                array[i] = classOf(array).cast(e);
                i++;
            }
            return array;
        } 
    
    2 回复  |  直到 14 年前
        1
  •  8
  •   BalusC    14 年前

    这仍然是实现它的最佳/最直接的方法吗?否则我将如何实现它?

    不是乔希·布洛赫的所作所为。看看 AbstractCollection#toArray() . 以下是JDK 1.6.0 U 22的相关性摘录。

    public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size();
        T[] r = a.length >= size 
            ? a 
            : (T[]) Array.newInstance(a.getClass().getComponentType(), size);
        Iterator<E> it = iterator();
    
        for (int i = 0; i < r.length; i++) {
            if (!it.hasNext()) { // fewer elements than expected
                if (a != r)
                    return Arrays.copyOf(r, i);
                r[i] = null; // null-terminate
                return r;
            }
            r[i] = (T) it.next();
        }
        return it.hasNext() ? finishToArray(r, it) : r;
    }
    

    源代码在 src.zip JDK的文件。您可以将它集成到任何像样的IDE中,比如eclipse/idea/netbeans,这样当您打开 AbstractCollection 班级。

    我能在没有警告的情况下用某种方式编码吗?

    不,使用 @SuppressWarnings("unchecked") 如果它困扰着你。

    也就是说,我建议延长 抽象集合 而不是执行 Collection 如果可能的话,至少您已经实现了基本的特性。

        2
  •  5
  •   axtavt    14 年前

    首先,如果它应该是 Collection.toArray() ,它不遵循约定-不应在数组中保留旧元素(请参见 javadoc )

    正确的实现如下所示:

    public <T> T[] toArray(T[] array) { 
        int size = size();
        if (array.length < size) { 
            // If array is too small, allocate the new one with the same component type
            array = Array.newInstance(array.getClass().getComponentType(), size);
        } else if (array.length > size) {
            // If array is to large, set the first unassigned element to null
            array[size] = null;
        }
    
        int i = 0;
        for (E e: this) {
            // No need for checked cast - ArrayStoreException will be thrown 
            // if types are incompatible, just as required
            array[i] = (T) e;
            i++;
        }
        return array;
    }