Получение списка элементов из ArrayList

предположим, у меня есть боб, как показано ниже.

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

тогда из метода я получаю List<Customer> обратно. Теперь предположим, что я хочу получить список всех членов "name" из списка. Очевидно, я могу пересечь и построить List<String> элемента "имя" себе.

однако мне было интересно, есть ли короткий путь или более эффективный способ этой техники, который кто-нибудь знает . Например,если я хочу получить список всех ключей в объекте карты, я получаю карту do.набор ключей.)( Что-то в этом роде. линия-это то, что я пытаюсь выяснить.

8 ответов


гуава имеет Lists.transform это может преобразовать List<F> до 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. Возвращаемый список представляет собой преобразованное представление fromList и fromList будет отражено в возвращенном списке и наоборот.

на function применяется лениво, вызывается при необходимости.

аналогичные преобразования live-view также предоставляются следующим образом:



могли бы использовать что-то вроде этого: http://code.google.com/p/lambdaj/


Я думаю, что это то, что вы должны были бы кодировать сами, в цикле.


можно использовать LambdaJ ' s конвертер интерфейс и содержит следующую строку:

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

вам нужно использовать цикл, но функция которую вы ищете называется map в функциональных языках. Возможно реализовать 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();
    }
}));

вы можете естественным образом изменить карту, чтобы взять коллекции вместо массивов, что устранит необходимость Arrays.asList и List.toArray


используя гуавы, вы можете использовать функции вместе с Iterables.transform, Collections2.transform или списки.transform создать Iterable, 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)) { ... }

я также писал об использовании интерфейсов для определенных свойств объекты (например,name здесь), чтобы помочь с консолидацией таких функций в моем блоге здесь.


.... есть ли короткий путь или более эффективный способ

Итак, вы ищете более эффективный способ сделать это:

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

?!!!!

или просто разные путь?

все предыдущие ответы на самом деле не более эффективны с точки зрения времени выполнения или кодирования. Однако они, без сомнения, более гибкие.

Другой альтернативой было бы включить Scala Groovy в вашем коде Java и используйте это:

list.map( _.name )

list.collect { it.name }

если скомпилированы, Groovy классы могут быть использованы из Java, или вы можете подключить их в качестве сценария.

вот образец для данного Customer класс с использованием Groovy в качестве скрипта.

    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.

здесь исходный код. Чтобы запустить его, вам просто нужен Java1.6 и заводной в classpath.