Как получить список значений конкретных полей из объектов, хранящихся в списке?

Скажем, у меня есть список объектов с двумя полями field1 и field2, оба типа String.

Как получить список всех значений field1 без необходимости перебирать список, если это вообще возможно?

Ответ 1

Объект является ссылкой на адрес памяти. Затем поля этих объектов являются другими ссылками на другие адреса памяти. Следовательно, список объектов - это список ссылок. Таким образом, невозможно, чтобы список имел доступ к объектным полям (ссылки, указанные в ссылках). Короткий ответ - нет.

Примечание: в любом случае вы найдете API, который делает то, что вы хотите, он все еще петли внутри.

Ответ 2

попробуйте следующее:

List<Entity> entities = getEntities();
List<Integer> listIntegerEntities = Lambda.extract(entities, Lambda.on(Entity.class).getFielf1());

LambdaJ позволяет обращаться к коллекциям без явных циклов, поэтому вместо того, чтобы иметь больше строк кода, чтобы итерировать список, вы позволяете LambdaJ делать это.

Ответ 3

К счастью, вы можете сделать это, используя Java 8 - Потоки

Предположим, что у вас есть объект с именем YourEntity

public class YourEntity {

    private String field1;
    private String field2;

    public YourEntity(String field1, String field2) {
        this.field1 = field1;
        this.field2 = field2;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public void setField2(String field2) {
        this.field2 = field2;
    }

    public String getField1() {
        return field1;
    }

    public String getField2() {
        return field2;
    }
}

Объявите список YourEntity, используя:

List<YourEntity> entities = Arrays.asList(new YourEntity("text1", "text2"), new YourEntity("text3", "text4"));

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

import java.util.stream.Collectors;

List<String> field1List = entities.stream().map(YourEntity::getField1).collect(Collectors.toList());

Или таким образом

import java.util.stream.Collectors;

List<String> field1List = entities.stream().map(urEntity -> urEntity.getField1()).collect(Collectors.toList());

Вы также можете распечатать все элементы, используя java 8:)

field1List.forEach(System.out::println);

Выход

text1
text3

Ответ 4

Ни java, ни языки, ни библиотеки JDK не делают того, что вы хотите. Вы можете либо использовать LambdaJ, либо дождаться появления Java 8, который должен включать лямбда-выражения.

Ответ 5

Зависит...

... относятся ли ваши вопросы к avoiding iterating over the collection:

  • с точки зрения простоты реализации в точках вызова
  • или с точки зрения сложности алгоритма.

Конкретно, вы имеете в виду:

  • вы не хотите сами вводить конструкцию итерации (просто используйте библиотеку удобства),
  • или вы действительно хотите что-то, что автоматически возвращало бы элементы в O (1) без необходимости их обработки (и иметь идеальный доступ)?

См. ниже решения и варианты.


Использование библиотеки удобств

Если это первый, посмотрите на Google Guava, LambdaJ, FunctionalJava или другие библиотеки, которые реализуют основные функциональные конструкции и позволят вам делать то, что вы хотите, несколькими выразительными вызовами. Но имейте в виду, что они делают то, что говорят на жестяне: они будут фильтровать, собирать или преобразовывать коллекцию и будут выполнять итерацию по ее элементам для этого.

Например:

  • Google Guava:

    Set<String> strings = buildSetStrings();  
    Collection<String> filteredStrings =
        Collections2.filter(strings, Predicates.containsPattern("^J"));  
    
  • Функциональная Java:

    Array<Integer> a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42);
    Array<Integer> b = a.filter(even);
    
  • LambdaJ:

    List<Integer> biggerThan3 = filter(greaterThan(3), asList(1, 2, 3, 4, 5));
    

Идеальный доступ

Если это второй, это невозможно как-есть, кроме, если вы все с нуля строили, чтобы управлять вашими объектами класс пользовательской коллекции, который будет индексировать ваши объекты на основе их значений полей при вставке.

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

Как упоминалось в комментариях ниже, dounyy ответ, проектирование такой пользовательской коллекции, вероятно, повлияет на API элементов, которые он примет (скорее всего, определив супер интерфейс для использования для типов элементов) или потребует довольно сложную реализацию для динамического решения участников (скорее всего, используя отражение), если вы когда-либо хотели, чтобы эта коллекция была общей.

Ответ 6

Нет, вы не можете. Вам нужно пройти весь список и получить каждое значение "field1" от каждого объекта.

Ответ 7

Возможно, вы можете создать хэш-карту таким образом:

HashMap<String, ArrayList<Object>> map;

Ключ будет полем. Таким образом, когда вы попросите HashMap вернуть вам объект, соответствующий требуемому полю, карта вернет вам массив ArrayList, коинирующий все элементы, которые имеют это поле.

Ответ 8

Без Итерации это невозможно. Вы можете как-либо уменьшить итерацию, но это необходимо.

Ответ 9

Добавьте значения записей в разные списки и с помощью одного или двух итераторов просто распечатайте раздельные значения. Следующее:

rs=st.executeQuery("select * from stu");
List data=new ArrayList();
List data1=new ArrayList();
while(rs.next())
{
   data.add(rs.getString(1));
   data1.add(rs.getString(2));
}
Iterator it=data.iterator();
Iterator it1=data1.iterator();
while(it1.hasNext())
{
   System.out.println(" "+it.next()+"  "+it1.next());
}

Ответ 10

Да!! Возможно. Но вы должны сделать какую-то кривую работу.

  • Создайте внутренний класс с требуемыми переменными. Например: здесь я буду использовать 2 переменные (TNAME и TABTYPE).

     public class storeTables {
            private String tablename = "";
            private String tabletype = "";
            public storeTables(String a, String b)
            {
                this.setTablename(a);
                this.setTabletype(b);
            }
            public void setTablename(String tablename) {
                this.tablename = tablename;
            }
            public String getTablename() {
                return tablename;
            }
            public void setTabletype(String tabletype) {
                this.tabletype = tabletype;
            }
            public String getTabletype() {
                return tabletype;
            }}
    
  • Создайте список внутреннего класса, созданного выше, и не забудьте его инкапсулировать.

    private List<storeTables> objlist= new ArrayList<storeTables>();
    
  • Получить значение, хранящееся в списке, как объект внутреннего класса.

    String Query="SELECT * FROM TAB";
    while(rs.next())
    {
    String tname=rs.getString("TNAME");
    String tabtype=rs.getString("TABTYPE");
    getObjlist().add(new storeTables(tname,tabtype));
            }
    
  • создайте DATAMODEL и перетащите список в datamodel

    private DataModel selectableItems= new ListDataModel(objlist);
    
  • получить данные с перекосом в другой список.

    List<storeTables> items= (List<storeTables>)selectableItems.getWrappedData();
    
  • В конце концов!!! печать данных.

    for(storeTables item:items){
    System.out.println(item.getTablename());
        }
    

ТАДА!!!! он будет печатать только имя табуляции, а не tabtype;) Поверьте, нет ничего невозможного в java Любые сомнения!!

Ответ 11

Древний вопрос, но я натолкнулся на него, смотря, чтобы посмотреть, смогу ли я улучшить аналогичное решение.

Вы можете реализовать интерфейс List<String> без создания флеш-вывода ArrayList<String> и, следовательно, не выполнять итерацию над родительским объектом.

final List<Entity> entities = getEntities()
final List<String> field1 = new AbstractList() {
    public String get(int index) {
        return entities.get(index).getField1();
    }
    public int size() {
        return entities.size();
    }
}

Это дает вам список без итерации над родительским объектом.

Случайный доступ к производному List<String> будет таким же дорогим, как случайный доступ к базовому List<Entity>; если вы используете реализацию List<Entity>, которая не обеспечивает быстрый произвольный доступ, вам, возможно, придется пройти через пару обручей (т.е. реализовать больше методов List<String>. Но это должно работать на 99% случаев, когда вам нужен легкий адаптер.