从ArrayList获取元素列表

时间:2010-06-24 17:37:02

标签: java arraylist

假设我有一个像下面这样的bean。

class Customer{
  private String code;
  private String name;
  private Integer value;
  //getters setters omitted for brevity
}

然后从一个方法我得到一个List<Customer>。现在让我们说我想从列表中获取所有成员“名称”的列表。显然,我可以自己遍历并构建一个List<String>元素“name”。

但是,我想知道这种技术是否有捷径或更有效的方法,任何人都知道。例如,如果我想获取Map对象中所有键的列表,我会得到map.keySet()。这条线上的东西是我想要找到的东西。

8 个答案:

答案 0 :(得分:6)

Guava有Lists.transform可以使用提供的Function<F,T>(或更确切地说,List<F>)将List<T>转换为Function<? super F,? extends T>

来自文档:

public static <F,T>
   List<T> transform(
               List<F> fromList,
               Function<? super F,? extends T> function
           )
     

返回将function应用于fromList的每个元素的列表。返回的列表是fromList的转换视图;对fromList的更改将反映在返回的列表中,反之亦然。

     

function懒惰地应用,在需要时调用。

类似的实时视图转换也提供如下:

答案 1 :(得分:5)

看起来你正在寻找与Perl的map函数相当的Java。这种事情可能会被添加到集合库中一次(如果)Java接收闭包。在那之前,我认为这是你能做的最好的事情:

List<String> list = new ArrayList<String>(customers.size());
for ( Customer c : customers ) {
    list.add(c.getName());
}

您还可以编写一个map函数,该函数使用简单的接口来提供映射函数。像这样:

public interface Transform<I, O> {
    O transform(I in);
}
public <I, O> List<O> map(Collection<I> coll, Transform<? super I, ? extends O> xfrm) {
    List<O> list = new ArrayList<O>(coll.size());
    for ( I in : coll ) {
        list.add(xfrm.transform(in));
    }
    return list;
}

答案 2 :(得分:4)

可以使用这样的东西: http://code.google.com/p/lambdaj/

答案 3 :(得分:3)

我认为这是你必须在循环中自己编码的东西。

答案 4 :(得分:2)

您可以使用LambdaJConverter界面,并拥有以下一行:

List<String> customerNames = convert(customerList, new Converter<Customer,String>() {
  public String convert(Customer customer) {
    return customer.getName();
  }
});

答案 5 :(得分:2)

您需要使用循环,但您正在寻找的函数在函数式语言中称为map。在Java中实现map是可能的,尽管它往往相当不优雅;这是我很久以前在我的“Java应该有的东西,但由于某种原因没有”库中实现的版本:

public interface MapFunction<T, U> {
    public U map(T source);
}

public static <T, U> U[] map(T[] objects, MapFunction<T, U> f) {
    if(objects.length == 0) {throw new IllegalArgumentException("Can't map onto an empty array");}
    @SuppressWarnings("unchecked") U[] rtn = (U[])Array.newInstance(f.map(objects[0]).getClass(), objects.length);
    for(int i = 0; i < objects.length; i++)
        rtn[i] = f.map(objects[i]);
    return rtn;
}

使用它,你可以这样做:

List<Customer> list = yourFunction();
List<String> names = Arrays.asList(map(list.toArray(new Customer[0]), new MapFunction<Customer, String>() {
    public String map(Customer c) {
        return c.getName();
    }
}));

您可以自然地将地图更改为采集而不是数组,这样就无需Arrays.asListList.toArray

答案 6 :(得分:2)

使用Guava,您可以使用Function以及Iterables.transformCollections2.transformLists.transform来创建Iterable,{{1分别为{}}或Collection

List

返回的Iterable<String> names = Iterables.transform(customers, new Function<Customer, String>() { public String apply(Customer from) { return from.getName(); } }); 是惰性的,并在迭代它时将函数应用于基础列表。对于包含名称的Iterable,您可以使用:

List<String>

List<String> names = Lists.transform(...);

当然,每次要执行此操作时写出匿名内部类ImmutableList<String> names = ImmutableList.copyOf(Iterables.transform(...)); 实现都是丑陋且冗长的,因此您可能希望Function可以使Function成为常量例如,名为Customer的类。

然后转换看起来更好(尤其是静态导入):

Customer.NAME

我还写过关于在对象的特定属性(例如for (String name : transform(customers, Customer.NAME)) { ... } )中使用接口来帮助在我的博客here上整合这些功能。

答案 7 :(得分:1)

  

....是否有捷径或更有效的方式

那么,您是否正在寻找一种更有效的方法来实现这一目标:

 List<String> names = new ArrayList<String>();
 for( Customer customer : yourCustomerList ) {
     names.add( customer.getName() );
 }

?!!!!

或只是 不同的 方式?

以前的所有答案在运行时和编码方面都没有那么高效。然而,毫无疑问,它们更具弹性。

另一种选择是在Java代码中包含 Scala Groovy并使用它:

<击> list.map( _.name )

list.collect { it.name }

如果编译,可以从Java使用Groovy类,或者您可以将它们作为脚本插入。

以下是使用Groovy作为脚本的给定Customer类的示例。

    List<Customer> customers = Arrays.asList( new Customer[]{
       new Customer("A","123",1),
       new Customer("B","456",2),
       new Customer("C","789",3),
       new Customer("D","012",4)
    });

    setVariable(customers, "list");
    evaluate("names = list.collect { it.name } ");
    List<String> names = (List<String>) getVariable("names");
    System.out.println("names = " + names);

输出:

names = [A, B, C, D]

注意:我提取了方法以便于阅读,但您可以在

下面看到它们

但是,这又是不同的,并不比常规for循环更有效。

这是complete source code。要运行它,您只需要在类路径中使用Java1.6和Groovy。