I was wondering if there's an effective way to extract an array of properties from an array of custom class objects. For example if I have something like this:
public class MyClass {
private Double p1;
private String p2;
private MyProperty p3;
public MyClass() {}
}
and in somewhere I have an ArrayList filled with objects of this class:
ArrayList<MyClass> listOfObjects = new ArrayList<>();
and I'd like to get a list of one of the properties:
ArrayList<MyProperty> listOfP3 = new ArrayList<>();
ArrayList<Double> listOfP1 = new ArrayList<>();
All I can think of is iterating through listOfObjects and copying the desired properties one by one to a new array... Is there a better way to do this?
EDIT:
If possible one that works with Java 7 also
Probably the cleanest way to do it is to use Streams. Something like this:
List<String> listOfP2= listOfObjects.stream().map(x->x.getP2()).collect(Collectors.toList());
Of course in MyClass you need to add a getter for those fields.
In Java 8 and higher, you can utilize the stream API (as #Amongalen already answered). There is a different possibility of accessing methods: Instead of x -> x.getP1() you can just write MyClass::getP1:
List<Double> p1List = myObjects.stream().map(MyClass::getP1).collect(Collectors.toList());
List<String> p2List = myObjects.stream().map(MyClass::getP2).collect(Collectors.toList());
List<MyProperty> p3List = myObjects.stream().map(MyClass::getP3).collect(Collectors.toList());
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have this, three different array lists:
ArrayList<type1> alista = new ArrayList<>();
ArrayList<type2> blistb = new ArrayList<>();
ArrayList<type3> clistc = new ArrayList<>();
I then create a new array list and put those 3 array lists into it:
ArrayList<Object> all_lists = new ArrayList<Object>();
all_lists.add(alista);
all_lists.add(blistb);
all_lists.add(clistc);
How do I add or remove objects inside all_lists: alista, blistb and clistc? I want to pass this all_lists back and forth between my methods inside my main(). I know doing it this way is probably wrong but I'd like to get this to work before I fix that with doing it better.
For example how do I get blistb out of that, then add one type of type2 I've created and then remove one type2 (from blistb). And then put it back (or create new all_lists?) into all_lists?
If I understand correctly, you want to be able to pass around all your data and make changes to the lists. First I would change the type of your lists to the List interface. This does not the function of your code but makes it easier if you'd want to change the List implementation in the future and it also saves some characters:
List<Type1> alista = new ArrayList<>();
List<Type2> blistb = new ArrayList<>();
List<Type3> clistc = new ArrayList<>();
We'll do the same with all_lists and at the same time, change its generic type to List to make life easier later:
List<List<Object>> allLists = new ArrayList<Object>();
(If Type1, Type2 and Type3 have some common ancestor that they all extend from, change the Object above to that type.)
To get one of your lists, blistb for instance, you need to know it's position in all_lists:
List<Type2> blistbReference = allLists.get(1); // Index starts from 0
This will probably be hard to maintain and to keep track of. There is also a risk that some future code change changes the order which will cause errors and headaches.
A better way to handle your lists would be to wrap them in a data object:
public class AllLists {
private List<Type1> alista;
private List<Type2> blistb;
private List<Type3> clistc;
public AllLists(List<Type1> alista, List<Type2> blistb, List<Type3> clistc) {
this.alista = alista;
this.blistb = blistb;
this.clistc = clistc;
}
public List<Type1> getAlista() {
return alista;
}
public List<Type1> getBlistb() {
return blistb;
}
public List<Type1> getClistc() {
return clistc;
}
}
// ......
AllLists allLists = new AllLists(alista, blistb, clistc);
You can now get your lists easily from the AllLists object and modify them as you like.
Type2 t = new Type2;
allLists.getBlistb().add(t);
You don't need to "put the list back" since Java is pass by reference. When you get the blistb from allLists, you are getting a reference to the same list object. Any changes to the reference is a change to the original list.
I changed type and variable names to be more standardized.
You should declare all_lists as a List of Lists; then, you can directly add and remove items to the Lists at specific indexes.
List<List> all_lists = new ArrayList<>();
all_lists.add(new ArrayList<A>(Arrays.asList(new A(1), new A(2), new A(3))));
all_lists.add(new ArrayList<B>(Arrays.asList(new B(4), new B(5))));
all_lists.add(new ArrayList<C>(Arrays.asList(new C(6))));
all_lists.get(1).add(new B(3));//add element to B List
You just need to keep track of which array is which:
in:
ArrayList<Object> all_lists = new ArrayList<Object>();
all_lists.add(alista);
all_lists.add(blistb);
all_lists.add(clistc);
all_lists.get(0) is alista
all_lists.get(1) is blistb
all_lists.get(2) is clistc
You remove the object from blistb by knowing which index it is in that list and removing it like normal.
all_lists.get(1).remove(2);
all_lists should be declared as ArrayList<ArrayList> (using raw-type which would require #SuppressWarnings("unchecked")).
#SuppressWarnings("unchecked")
ArrayList<ArrayList> all_lists = new ArrayList<>();
all_lists.add(alista);
all_lists.add(blistb);
all_lists.add(clistc);
clistc.add(new type3());
all_lists.get(0).add(new type1()); // add type1 object to alista
all_lists.get(1).add(new type2()); // add type2 object to blistb
all_lists.get(2).remove(0); // remove the 1st element of clistc
However, it would be better and more type-safe object-oriented way to create a wrapper class instead of all_list:
class ListWrapper {
private List<type1> aListA;
private List<type2> bListB;
private List<type3> cListC;
// constructor(s), getters/setters
public void addType1(type1 t1) {
aListA.add(t1);
}
// etc.
}
Is it possible to store two different data types in arraylist ?
for example
ArrayList<String,int> arr = new ArrayList<>();
if I want to store a string and integer into one index of an arrayList. How can I do that and how will I be able to access it?
To do that, you should include both (the string and the integer) in one object having the string and integer as fields. It could look like:
public class StringAndInteger {
public String string;
public Integer integer;
}
I suggest giving it a meaningful name, setting the fields private and add getters and setters.
You can make it list of lists.
List<List<?>> list = new ArrayList<>();
list.add(Arrays.asList("str1", 8));
list.add(Arrays.asList("str91", 98));
System.out.println(list);
Of course, a better way would be to use Map instead of this. Also you cannot use primitive type with collections.
ArrayList uses Array as its under-lying data structure, which can not add heterogeneous data-types. To achieve so, Just Make a class in your code. Declare the instance variables in this class. If you want to add String and Integer Then write it like this:
public class YourClass{
//Your code
...
//Create a class in your existing class. It is just used like a data-type.
static class SampleClass {
public String str;
public Integer intgr;
}
//Now You can use this class like a data-type
public void myMethod(){
ArrayList<SampleClass> myList=new ArrayList();
//add values.
SampleClass ob1=new SampleClass('name1',12345);
SampleClass ob2=new SampleClass('name2',12345234);
myList.add(ob1);
myList.add(ob2);
myList.add(new SampleClass('name3', 12));
//get values
for(int i=0;i<myList.size();i++){
String stringValue=myList.get(i).str;
String intValue=myList.get(i).intgr;
system.out.println(stringValue);
system.out.println(intValue);
}
}
Alright, so I've been working with PHP for most of my career and find myself needing to use Java. In my case, the biggest issue I have is creating and manipulating arrays in Java.
Example in PHP:
$cars = array(1 => array("stats"=> array("velocity"=>100,
"acceleration"=>0,
"energy"=>30000,
"distance"=>200
)
),
2 => array("stats"=> array("velocity"=>3,
"acceleration"=>6,
"energy"=>30000,
"distance"=>200)
)
);
I'm trying to re-create this type of array in Java but I'm having trouble with initializing it. Is the array considered a String in this case? And must the size of the array be set prior to creating it? e.g: String[][][] car = new String[][][]?
Exactly as aet said in a comment - if you're considering doing this in java - don't. You're doing it wrong.
You should have a class for Car
public class Car {
private int velocity;
private int acceleration;
private int energy;
private int distance;
//getters and setters, a constructor that gets all the property values ...
}
and then store your cars in some collection. An ArrayList is the easiest way:
List<Car> cars = new ArrayList<Car>();
cars.add(new Car(100,0,30000,200));
cars.add(new Car(3,6,30000,200));
Accessing the list of cars would then look like this:
cars.get(0).getVelocity(); //collection indexes start at 0
I think Java doesn't have TRUE multidimensional arrays. An array which is accessed like a[i][j][k] is simply an array, of arrays, of arrays.
You can try the following construct:
String[][] car = new String [][] { { "X0", "Y0"},
{ "X1", "Y1"},
{ "X2", "Y2"},
{ "X3", "Y3"},
{ "X4", "Y4"} };
1) is that "stats" index nesserly? if not, you can:
Map<String, Integer>[] cars = new HashMap<String, Integer>[your length here];
this will index your cars by numbers, skip the "stats" index, and allow you to index the last integer by string:
int velocityOfSecondCar = cars[1].get("velocity"); //note indexing from 0
2) if "stats" index is nesserly, you would have to go one dimension deeper
What you have in PHP there would typically be represented as nested Map instances in Java. For example:
HashMap<Integer,Map<String,Map<String,Integer>>> data = new HashMap<>();
Then you could get values (assuming all levels of the Hash are populated correctly) by saying:
int velocity = data.get(1).get("stats").get("velocity");
Populating nested maps like this can be complicated, and you would typically use a helper method to make sure all the 'parent' levels are populated before you add a data member.
Yes, lenghts must be provided when initializing an array. Hence, your array would look something like this:
int lenght1=x;
int length2=y;
int lenght3=z;
String[][][] car = new String[lenght1][lenght2][lenght3]
I'm no PHP developer myself, but Classes within the array will obey the OOP rules Java implements in terms of abstraction and inheritance. So when you retrieve the elements you can use their corresponding interfaces whatever the class or interface that contains them are.
On the other hand, if you can't know the array lenghts before the initialization you can use class ArrayList, which is almost like a Vector. This class modify its internal length if new elements are added. Along with ArrayList you have a complete set of data structures in the Java specs to store the elements, like Maps, Sets, Lists, etc...
When instantiating an ArrayList you should specify which class or interface will describe the objects you are storing within the data structure, so you'll have to use generics to instantiate the structure. In your case:
ArrayList<String> dim1=new ArrayList<String>();
ArrayList<ArrayList<String>> dim2=new ArrayList<ArrayList<String>>();
ArrayList<ArrayList<ArrayList<String>>> dim3= new ArrayList<ArrayList<ArrayList<String>>>();
As you can see this structure is way sexier than the simple arrays above, but obviusly will require more care to deal with it. Don't forget to instantiate your arraylists before putting them in your 3d matrix, or you'll get an exception later for accesing a null objects.
try this..
Map<Integer, HashMap<String, HashMap<String, Integer>>> map = new HashMap<>();
HashMap<String, Integer> hm = new HashMap<>();
hm.put("Velocity", 1);
hm.put("acceleration", 2);
HashMap<String, HashMap<String, Integer>> state1 = new HashMap<>();
state1.put("state1", hm);
map.put(1, state1);
System.out.println(map);
Hello I have a compiling problem with this peace of code. How can I perform a safe add to data variable?
import java.util.*;
public class Foo
{
private TreeSet<? extends Collection<String>> data;
public Foo()
{
data = new TreeSet<ArrayList<String>>();
data.add("Goofy"); //this action generates a compile error
}
}
You're trying to add a String to a TreeSet of ArrayLists of Strings. You would need to add an ArrayList. Probably
ArrayList<String> list = new ArrayList<>();
list.add("Goofy");
data.add(list);
That is, assuming you're not using an overcomplicated design, which you very much probably are.
data is a collection of ArrayList and you are trying to add a String
You need to add the String to an array list first
ArrayList<String> list = new ArrayList<String>();
list.add("Goofy");
data.add(list);
or change data to be a TreeSet of Strings
private TreeSet<String> data;
data = new TreeSet<String>();
data.add("Goofy");
I have some Java code which contains some arrays. Say one of them is b. I have a string a whose value points to the names of those arrays at different times. So if a currently contains b, I want to access the 3rd element of b through a. Something which I could have done in Javascript with window[a][2]. is it possible in Java?
Use collections. Looks like you're looking for HashMap
Something like that:
Map<String, List<String>> map = new HashMap<String, List<String>>();
Based on your comments above, I'll give you a pseudo code answer:
Write the handler like this:
public class MyHandler implements YourHandlerInterface {
private String[] array;
public MyHandler(String[] array) {
this.array = array;
}
// your methods that have to access the array.
}
Then, when you can use them somehow like:
fileMenu.addHandler(new MyHandler(fileMenuArray));
editMenu.addHandler(new MyHandler(editMenuArray));
So you don't use dynamically generated variable names and still only have to implement it once.