Java:generic方法 - 向vararg添加元素

时间:2016-07-12 12:56:26

标签: java generics methods

我想在这里做到这一点,它实际上有效但不知何故我不认为这是一个很好的解决方案:

class A5<T> implements A4<T> {

    private final T[] elements;

    A5(T... elements) {
        this.elements = elements;
    }


    public <R> A5<R> map(Function<T, R> function) {
        List<R> liste = new LinkedList<>();
        for (T element : elements) {
            liste.add(function.apply(element));
        }
        Object[] objects = new Object[liste.size()];
        int counter = 0;
        for (R element : liste) {
            objects[counter] = liste.get(counter++);
        }
        return new A5(objects);
    }
}

对我而言,Object[]是个问题,但我无法创建R[]数组。有人有解决方案吗?改变CTOR和地图签名并不是我想要的。只有身体才能改变。

4 个答案:

答案 0 :(得分:2)

您无法创建通用数组,因此除非您将T[]更改为课程List<T>中的A5,否则您需要创建Object[]

您的代码可以简化一点。您可以使用Java 8 Stream映射元素并将其收集到Object[],然后将此Object[]强制转换为R[]@SuppressWarnings("unchecked")隐藏了未经检查的演员阵容产生的警告:

class A5<T> implements A4<T> {

    private final T[] elements;

    A5(T... elements) {
        this.elements = elements;
    }

    @SuppressWarnings("unchecked")
    public <R> A5<R> map(Function<T, R> function) {
        return new A5<>((R[]) Arrays.stream(elements).map(function).toArray());
    }
}

答案 1 :(得分:1)

如果您被允许添加ctor,您可以将数据存储在列表中,从而执行

class A5<T> implements A4<T> {

    private final List<T> elements;

    A5(T... elements) {
        this.elements = Arrays.asList(elements);
    }

    private A5(List<T> elements) {
        this.elements = elements;
    }


    public <R> A5<R> map(Function<T, R> function) {
        List<R> list = elements.stream().map(function)
            .collect(Collectors.toList());
        return new A5(list);
    }
}

答案 2 :(得分:0)

你可以试试:

public <R> A5<R> map(Function<T, R> function) {
    List<R> liste = new LinkedList<>();
    for (T element : elements) {
        liste.add(function.apply(element));
    }

    Object[] objects = liste.toArray();

    return new A5(objects);
}

答案 3 :(得分:0)

不可能。

您可以做的最好的事情是获取函数返回的最非特定类型的对象,并使用它来创建一个新数组。显然,当数组为空或只从函数返回null时,它不会工作。

    Set<Class<?>> types = new HashSet<>();
    List<R> liste = new LinkedList<>();
    for (T element : elements) {
        R mapped = function.apply(element);
        types.add(mapped.getClass());
        liste.add(mapped);
    }

    Class<?> elementType = getMostUnspecifc(types);

    return new A5<R>(liste.toArray((R[]) Array.newInstance(elementType, liste.size()));

使用辅助方法

static Class<?> getMostUnspecifc(Set<Class<?>> types) {
    if (types.isEmpty()) {
        return Object.class;
    }
    Class<?> unspecific = types.iterator().next();
    for (Class<?> type : types) {
        if (!unspecific.isAssignableFrom(type)) {
            unspecific = type;
        }
    }
    return unspecific;
}