在集合上调用方法以添加到另一个集合

时间:2013-05-25 18:04:00

标签: java collections

我必须继续编写比我想要的更长的代码,而且我必须做很多次。

Collection<MiClase> collection1 = new ArrayList<MiClase>;
Collection<String> collection2 = new ArrayList<String>;
// I currently do this
for (MiClase c : collection1){
    collection2.add(c.nombre()); // nombre() returns String
}

是否有什么可以缩短它?

// I want something like
collection2.addAll(collection1, MiClase.nombre);

3 个答案:

答案 0 :(得分:5)

没有内置的java函数可以做到这一点¹。你可以使用Guavas'Collections2#transform(collection, function)'

因此,您的代码看起来像

// nombres = collections2, miClasses = collection1
nombres.addAll(Collections2.transform(miClasses, new Function() {
    @Override
    public String apply (MiClasse miClasse) {
        return miClasse.nombre();
    }
}));

但这真的很麻烦,只是为了删除一个简单的循环可能是一种过度杀伤。

修改

1 - 正如A.R.S.所指出的,在Java 8 lambda表达式和改进的集合API之前没有内置。链接有一些很酷的例子:http://www.javabeat.net/2012/05/enhanced-collections-api-in-java-8-supports-lambda-expressions/

答案 1 :(得分:2)

完整性比其他任何事情更多......

您可以使用reflection编写一个方法来执行此操作:

static <A,B> void addAll(Collection<B> dest, Collection<A> source, String methodName)
      throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
  for (A a: source)
  {
    // can optimize this to only get method once if all objects have same type
    Method m = a.getClass().getMethod(methodName);
    dest.add((B)m.invoke(a));
  }
}

用法/示例:

ArrayList<String> s = new ArrayList<String>();
List<Integer> i = Arrays.asList(1,2,3);
addAll(s, i, "toString");
System.out.println(s);

如果您愿意,也可以添加方法参数。

Test

为什么我会&gt;&gt; NOT&lt;&lt;推荐

如果抛出3个例外并不让你担心......(当然,你可以try - catch,而是完全避免例外)

(人类)失败的几点:(这些都将显示为运行时错误,但首选编译时错误)

  • 方法名称为misspelt
  • 该方法甚至不存在
  • 该方法不返回B
  • 类型的对象

答案 2 :(得分:0)

使用Stream API的几种方法中的两种:

对于

Collection<MiClase> collection1 = new ArrayList<>;
Collection<String> collection2 = new ArrayList<>;

MiClase#nombre返回String作为OP提到:

collection1.stream()
        .map(MiClase::nombre)
        .collect(Collectors.toList())
        .forEach(collection2::add);

collection2.addAll(collection1.stream()
        .map(MiClase::nombre)
        .collect(Collectors.toList()));