Reputation: 699
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?
Upvotes: 68
Views: 238783
Reputation: 59
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
Upvotes: 3
Reputation: 7149
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
Upvotes: 106
Reputation: 7248
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.
Upvotes: 2
Reputation: 55
Yes!! Its possible. But you have to do some crooked work.
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;
}}
Create a List of the inner class created above and dont forget to encapsulate it.
private List<storeTables> objlist= new ArrayList<storeTables>();
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));
}
create a DATAMODEL and push the list to the datamodel
private DataModel selectableItems= new ListDataModel(objlist);
get the warpped data to another list.
List<storeTables> items= (List<storeTables>)selectableItems.getWrappedData();
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!!
Upvotes: 1
Reputation: 1
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());
}
Upvotes: 0
Reputation: 22663
... whether your questions refers to avoiding iterating over the collection
either:
Concretely, do you mean:
See below for solutions and options.
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:
Set<String> strings = buildSetStrings();
Collection<String> filteredStrings =
Collections2.filter(strings, Predicates.containsPattern("^J"));
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);
List<Integer> biggerThan3 = filter(greaterThan(3), asList(1, 2, 3, 4, 5));
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.
Upvotes: 5
Reputation: 1687
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.
Upvotes: 11
Reputation: 7899
Without Iterating this is not possible .You can reduce iteration somehow but it is must.
Upvotes: 0
Reputation: 1120
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.
Upvotes: 0
Reputation: 115328
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.
Upvotes: 4
Reputation: 665
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.
Upvotes: 9
Reputation: 938
No, you can't. You have to traverse the whole list and get each "field1" value from each object.
Upvotes: 0