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

Скажем, у меня есть боб как ниже.

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

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

Однако я задавался вопросом, существует ли короткий путь или больше effiecient пути к этой технике, которую любой знает. Например, если я хочу добраться, список всех ключей в Карте возражают, что я добираюсь, делают map.keySet (). Что-то вдоль той строки - то, что я пытаюсь узнать.

6
задан CoolBeans 24 June 2010 в 17:37
поделиться

8 ответов

В Guava есть Lists.transform который может преобразовать List в List, используя предоставленную Function (или, скорее, Function).

Из документации:

public static 
 List transform(
 List fromList,
 Function function
 )

Возвращает список, который применяет функцию к каждому элементу fromList. Возвращаемый список является преобразованным представлением fromList; изменения в fromList будут отражены в возвращаемом списке и наоборот.

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

Подобные преобразования в реальном времени также предоставляются следующим образом:

6
ответ дан 8 December 2019 в 04:28
поделиться

Похоже, вы ищете Java-эквивалент map -функции Perl. Подобные вещи могут быть добавлены в библиотеку коллекций, как только (если) 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;
}
5
ответ дан 8 December 2019 в 04:28
поделиться

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

3
ответ дан 8 December 2019 в 04:28
поделиться

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

List<String> customerNames = convert(customerList, new Converter<Customer,String>() {
  public String convert(Customer customer) {
    return customer.getName();
  }
});
2
ответ дан 8 December 2019 в 04:28
поделиться

Вам нужно использовать цикл, но искомая функция на функциональных языках называется 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.asList и List.toArray

2
ответ дан 8 December 2019 в 04:28
поделиться

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

4
ответ дан 8 December 2019 в 04:28
поделиться

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

Возвращенный Iterable является ленивым и применяет функцию к базовому списку, когда вы выполняете итерацию по нему. Для списка List , содержащего имена, вы можете использовать:

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 здесь), чтобы помочь с консолидацией таких функций на моем блог здесь .

2
ответ дан 8 December 2019 в 04:28
поделиться

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

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

 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 и Groovy в пути к классам.

1
ответ дан 8 December 2019 в 04:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: