代码之家  ›  专栏  ›  技术社区  ›  CoolBeans Jake

从数组列表中获取元素列表

  •  6
  • CoolBeans Jake  · 技术社区  · 15 年前

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

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

    然后通过一种方法我得到了 List<Customer> 回来。现在假设我想从列表中获取所有成员“name”的列表。显然,我可以穿越并建立一个 List<String> 我自己的元素“name”。

    然而,我想知道是否有一个捷径或更有效的方法,以这种技术,任何人都知道。例如,如果我想得到一个映射对象中所有键的列表,我会得到do map.keyset()。这条线的某些东西正是我想知道的。

    8 回复  |  直到 14 年前
        1
  •  6
  •   polygenelubricants    15 年前

    番石榴 Lists.transform 可以改变 List<F> 到A List<T> ,使用提供的 Function<F,T> (或更确切地说, Function<? super F,? extends T> )

    从文档中:

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

    返回应用的列表 function 到的每个元素 fromList . 返回的列表是的转换视图 来自列表 改变 来自列表 将反映在返回的列表中,反之亦然。

    这个 功能 是延迟应用的,需要时调用。

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

        2
  •  5
  •   Mark Peters    15 年前

    看起来你在寻找Perl的Java等价物 map 功能。一旦Java接收闭包,这种情况可能会被添加到集合库中。在那之前,我认为这是你能做的最好的:

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

    你也可以写一个 地图 使用简单接口提供映射函数的函数。像这样:

    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;
    }
    
        3
  •  4
  •   JoshP    15 年前

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

        4
  •  3
  •   froadie    15 年前

    我认为这是一个你必须自己编码的循环。

        5
  •  2
  •   David Rabinowitz    15 年前

    你可以使用 LambdaJ Converter interface and have the following line:

    List<String> customerNames = convert(customerList, new Converter<Customer,String>() {
      public String convert(Customer customer) {
        return customer.getName();
      }
    });
    
        6
  •  2
  •   Michael Mrozek    15 年前

    您需要使用一个循环,但是您要查找的函数被调用 map 功能语言。可以实现 地图 在Java中,虽然它往往是不雅的;这里是我以前在我的“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();
        }
    }));
    

    您可以自然地更改map以获取集合而不是数组,这样就不需要 Arrays.asList List.toArray

        7
  •  2
  •   ColinD    14 年前

    使用 Guava ,可以使用 Function 随着 Iterables.transform , Collections2.transform Lists.transform 创建一个 Iterable , Collection List 分别。

    Iterable<String> names = Iterables.transform(customers, 
        new Function<Customer, String>() {
          public String apply(Customer from) {
            return from.getName();
          }
        });
    

    归还的人 可迭代的 是懒惰的,并在迭代时将函数应用于底层列表。对于一个 List<String> containing the names, you could use:

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

    ImmutableList<String> names = ImmutableList.copyOf(Iterables.transform(...));
    

    当然,写出匿名的内部类 Function 每次您希望这样做时,实现都是丑陋和冗长的,因此您可能希望 功能 Customer 类,称为 Customer.NAME 例如。

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

    for (String name : transform(customers, Customer.NAME)) { ... }
    

    我还写过使用接口来处理对象的特定属性(例如 name 这里)帮助整合我的博客上的这些功能 here .

        8
  •  1
  •   OscarRyz    15 年前

    …有捷径或更有效的方法吗

    所以,你是否在寻找一种更有效的方法来做到这一点:

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

    ?!!!!!!

    或者只是一个 不同的 方式?

    之前的所有答案在运行时和编码方面都没有真正的效率。但毫无疑问,它们更灵活。

    另一种选择是包括 斯卡拉 在Java代码中使用Groovy:

    list.map( _.name )

    list.collect { it.name }
    

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

    这是给你的样品 Customer class using Groovy as script.

        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。