How to get a list of specific fields values from objects stored in a list?

JavaCollections

Java Problem Overview


Say I have an list of objects with two fields field1 and field2, both of String type.

How do I get a list of all field1 values without having to iterate over the list, if it is at all possible?

Java Solutions


Solution 1 - Java

Fortunately, you can do this using Java 8 - Streams

Assume you have an entity named 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;
    }
}

Declare you list of YourEntity using:

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

You can extract the list of field1 in one shot in this way:

import java.util.stream.Collectors;

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

Or in this way

import java.util.stream.Collectors;

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

You can print all the items also using java 8 :)

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

Output

text1
text3

Solution 2 - Java

try this:

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

the LambdaJ allows to access collections without explicit loops, so instead of have more lines of code to iterate the list yourself, you let LambdaJ do it.

Solution 3 - Java

An object is a reference towards a memory address. Then, the fields of this objects are other references towards other memory addresses. Hence, a list of objects is a list of references. So, it's impossible for the list to direclty access the object fields (references given by the references). The short answer is no.

Note: anyway you'll find an API that does what you want, it still loops in the inside.

Solution 4 - Java

Depends...

... whether your questions refers to avoiding iterating over the collection either:

  • in terms of ease of implementation at call points
  • or in terms of the algorithmic complexity.

Concretely, do you mean:

  • you don't want to type in an iterating construct yourself (simply use a convenience library),
  • or you actually want something that would return elements auto-magically in O(1) without needing to process them (and have perfect access)?

See below for solutions and options.


Using Convenience Libraries

If it's the first one, then look at Google Guava, LambdaJ, FunctionalJava or other libraries that implement basic functional constructs and will allow you to do what you want in a few expressive calls. But keep in mind these do what is says on the tin: they will filter, collect or transform a collection, and will iterate through its elements to do this.

For instance:

  • Google Guava:

     Set<String> strings = buildSetStrings();  
     Collection<String> filteredStrings =
         Collections2.filter(strings, Predicates.containsPattern("^J"));  
    
  • Functional 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));
    

Perfect Access

If it's the second one, this is not possible as-is, except if you architectured everything from the start so that your objects should be managed by a custom collection class that would indexing your objects based on their field values on insertion.

It would keep them in buckets indexed by said value to be readily available for you to retrieve them as a list or set on demand.

As mentioned in the comments below dounyy's answer, designing such a custom collection would probably have an impact on the API of the elements it would accept (most likely by defining a super interface to use for element types), or would require a fairly intricate implementation to resolve members dynamically (most likely by using reflection), if you ever wanted this collection to be generic.

Solution 5 - Java

Neither java as a language nor JDK libraries do not do what you want yet. You can either use LambdaJ or wait for Java 8 that is expected to include lambda expressions.

Solution 6 - Java

Ancient question, but I came upon it while looking to see if I could improve on a similar solution.

You can implement the List<String> interface without creating a fleshed-out ArrayList<String>, and thus not iterating over the parent object.

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();
    }
}

That gives you a List without iterating over the parent object.

Random access to the derived List<String> will be as expensive as random access to the underlying List<Entity>; if you're using an implementation of List<Entity> that does not provide quick random access, you might have to jump through a couple of hoops (i.e. implementing more methods of List<String>. But this should work for 99% of the cases where you need a light-weight adapter.

Solution 7 - Java

Let the object be of the following class.

public class Bike {

    String bikeModel;
    Int price;
}

And now there is list of bikes called bikeList of type List

So now we want a list of bikemodels of all the bikes in the above list.

bikeList.map{ Bike b -> b.bikeModel }.toCollection(arrayListOf())

returns an array list of first field of all the bike objects in the bikeList

Solution 8 - Java

Yes!! Its possible. But you have to do some crooked work.

  1. Create a inner class with required variables. Eg: here am going to use 2 variables.( TNAME and 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;
     		}}
    
  2. Create a List of the inner class created above and dont forget to encapsulate it.

     private List<storeTables> objlist= new ArrayList<storeTables>();
    
  3. Get the value stored to the list as a inner class object.

     String Query="SELECT * FROM TAB";
     while(rs.next())
     {
     String tname=rs.getString("TNAME");
     String tabtype=rs.getString("TABTYPE");
     getObjlist().add(new storeTables(tname,tabtype));
         	}
    
  4. create a DATAMODEL and push the list to the datamodel

     private DataModel selectableItems= new ListDataModel(objlist);
    
  5. get the warpped data to another list.

     List<storeTables> items= (List<storeTables>)selectableItems.getWrappedData();
    
  6. Finally!!! printing the data.

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

TADA !!!! it will print only the tablename and not the tabtype ;) Believe that there is nothing impossible in java Any doubts!!

Solution 9 - Java

No, you can't. You have to traverse the whole list and get each "field1" value from each object.

Solution 10 - Java

Maybe you could create an hashmap in this way:

HashMap<String, ArrayList<Object>> map;

The key would be the field. Doing this way, when you ask the HashMap to retrieve you the object corresponding to the field that you want, the map would return you an ArrayList cointaing all of the elements which has that field.

Solution 11 - Java

Without Iterating this is not possible .You can reduce iteration somehow but it is must.

Solution 12 - Java

Add the values of records in different lists and by using the one or two iterator simply print the seperate values.like follows:

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());
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1343585View Question on Stackoverflow
Solution 1 - JavaJad ChahineView Answer on Stackoverflow
Solution 2 - JavaEuclides MulémbwèView Answer on Stackoverflow
Solution 3 - JavadounyyView Answer on Stackoverflow
Solution 4 - JavahaylemView Answer on Stackoverflow
Solution 5 - JavaAlexRView Answer on Stackoverflow
Solution 6 - Javauser295691View Answer on Stackoverflow
Solution 7 - JavamanasBVSSView Answer on Stackoverflow
Solution 8 - JavaHarish AravindView Answer on Stackoverflow
Solution 9 - JavastzoannosView Answer on Stackoverflow
Solution 10 - JavasmellyarmpitsView Answer on Stackoverflow
Solution 11 - JavaamicnghView Answer on Stackoverflow
Solution 12 - JavaDattatraya SatputeView Answer on Stackoverflow