Converting Arraylists with abstract objects - java

Good morning all,
While writing my GUI I ran into a problem with my Arraylist.
In my Vereniging class there is a ArrayList containing Persoon objects, which are either Lid or Medewerker.
Now what I need is to filter all the Lid objects from that list and make a new Arraylist with Lid objects.
Does anyone know if this is possible?
I've tried running a enhanced for loop and adding the objects to a new Arraylist but it says the datatype doesnt meet (trying to add Persoon to a Lid list)
Classes;
Vereniging
public class Vereniging {
private String naam;
private ArrayList<Persoon> personen;
private ArrayList<Vliegtuig> vliegtuigen;
private ArrayList<Vlucht> vluchten;
private ArrayList<Hangaar> hangaars;
private DataHandler handler = new Database();
public Vereniging(String naam){
this.naam = naam;
personen = new ArrayList<>();
vliegtuigen = new ArrayList<>();
vluchten = new ArrayList<>();
hangaars = new ArrayList<>();
}
public ArrayList<Persoon> getPersonen() {
return personen;
}
Persoon
public abstract class Persoon implements Comparable<Persoon>{
private String voornaam;
private String tussenvoegsel;
private String achternaam;
private String woonplaats;
private String geslacht;
private String rekeningnr;
Persoon(String voornaam, String tussenvoegsel, String achternaam, String
woonplaats,
String geslacht, String rekeningnr){
this.voornaam = voornaam;
this.tussenvoegsel = tussenvoegsel;
this.achternaam = achternaam;
this.woonplaats = woonplaats;
this.geslacht = geslacht;
this.rekeningnr = rekeningnr;
}
Lid
public class Lid extends Persoon {
private String gebnaam;
private String wachtwoord;
private String rol;
public Lid(String voornaam, String tussenvoegsel, String achternaam, String woonplaats, String geslacht,
String rekeningnr, String gebnaam, String wachtwoord, String rol) {
super(voornaam, tussenvoegsel, achternaam, woonplaats, geslacht, rekeningnr);
this.gebnaam = gebnaam;
this.wachtwoord = wachtwoord;
this.rol = rol;
}

You can use the type comparison operator: instanceof. Which lets you compare if a variable is an instance of a class (or a subclass).
See the following example which iterates over the personen list and then uses the instanceof to determine if it in fact is an instance of Lid or not:
List<Lid> lids = new ArrayList<>();
for(Persoon persoon : personen){
if(persoon instanceof Lid){
// safe cast and add to lids
lids.add((Lid) persoon);
}
}
If you happen to use Java 8, you can make us of the new Stream API:
List<Lid> lids = personen.stream() // create a stream of persoonen
.filter(Lid.class::isInstance) // equivalent to using instanceof
.map(Lid.class::cast) // equivalent to casting
.collect(Collectors.toList()); // creating a list

As I can see you want to add object of parent into array list of child type.
So when your are iterating through list of persoon, check type of persoon by using instanceOf then type case that to Lid and add it to your new list.
Hope this will resolve your problem.
More Enhance solution can be as following.
personen.stream().filter(p->p instanceOf Lid).map(p->(Lid)p).collect(Collectors.toList());
by using stream API of Java 8 you can do it in a single line.
Thanks!

Related

What's the ideal way of combining two Object Arrays in Java

Class A:
public class A{
private String Id;
private List<Product> products = new ArrayList<>();
}
public class Product{
private String prodId;
private String color;
private String size;
}
Example:
A = { "Id": 1 , products: [{"prodId":"Prod1", "color":"Red", "size":"L"},
{"prodId":"Prod2", "color":"Green", "size":"L"}] }
Class B:
public class B{
private String Id;
private List<ProductAvail> productAvail = new ArrayList<>();
}
public class ProductAvail{
private String prodId;
private String availability;
private String region;
}
Example:
B = { "Id": 1 , productAvail: [{"prodId":"Prod1", "availability":"Y", "region":"AA"},
{"prodId":"Prod2", "availability":"N", "region":"BB"}] }
I want to combine them into one like
public class C{
private String Id;
private List<Catalog> catalog = new ArrayList<>();
}
public class Catalog{
private String prodId;
private String color;
private String size;
private String availability;
private String region;
}
C = { "Id": 1 , catalog: [{"prodId":"Prod1", "color":"Red", "size":"L", "availability":"Y", "region":"AA"},
{"prodId":"Prod2", "color":"Green", "size":"L", "availability":"N", "region":"BB"}] }
What's the ideal way to do this in Java without using two for loops?
Given:
String aJson = "{ \"id\": 1 ,\"products\": [{\"prodId\":\"Prod1\", \"color\":\"Red\", \"size\":\"L\"}, {\"prodId\":\"Prod2\", \"color\":\"Green\", \"size\":\"L\"}] }";
String bJson = "{ \"id\": 1 ,\"productAvail\": [{\"prodId\":\"Prod1\", \"availability\":\"Y\", \"region\":\"AA\"}, {\"prodId\":\"Prod2\", \"availability\":\"N\", \"region\":\"BB\"}] }";
You can do:
ObjectMapper objectMapper = new ObjectMapper();
A a = objectMapper.readValue(aJson, A.class);
B b = objectMapper.readValue(bJson, B.class);
Map<String, ProductAvail> idToProductAvail = b.getProductAvail().stream()
.collect(Collectors.toMap(ProductAvail::getProdId, Function.identity()));
List<Catalog> catalogs = a.getProducts().stream()
.map(p -> {
ProductAvail pa = idToProductAvail.get(p.getProdId());
return new Catalog(pa.getProdId(), p.getColor(), p.getSize(),
pa.getAvailability(), pa.getRegion());
}).collect(Collectors.toList());
C c = new C(a.getId(), catalogs);
System.out.println(objectMapper.writeValueAsString(c));
Output:
{"id":"1","catalog":[{"prodId":"Prod1","color":"Red","size":"L","availability":"Y","region":"AA"},{"prodId":"Prod2","color":"Green","size":"L","availability":"N","region":"BB"}]}
Assuming you want to do this action in Java, after parsing your source data, you have two choices.
Guarantee that your source data is ordered by prodId for both lists, and that every Product has a corresponding ProductAvail. You can then simply assume that the index of the first has a valid entry at the same index in the second and traverse them both with a single loop.
Change your source data and class members such that you have Maps instead of Lists as output, using prodId as the key for each entry. You can then iterate the keys from the map of Products and use them to access both the Product and ProductAvail maps in a single loop.
-
If you can't make the guarantees from (1) or the changes from (2), you're stuck with your worst case of foreach product { foreach productavail { ... } } because you have to discover the correct ProductAvail for each Product.
You could take steps mitigate the impact by nulling discovered inner list members and skipping nulls, or by using parallelStream to throw the inner loop for each outer iteration at a different thread, but no action at this point avoids needing some riff on loop{loop{}} - as a best case.

Add additional attributes to JSON response in Java

I have a service which is returning a List in JSON format.
Please find below code :
public List<SampleList> getValues() {
List<SampleList> sample = null;
sample= DAOFactory.sampleDAO.findByCriteria().add(Restrictions.isNull("endDate")).list();
return sample;
}
Class SampleList.java
public class SampleList {
private Integer categoryId;
private String categoryName;
//getter setter
}
Now my service is returning the JSON like below
{
categoryId : 1,
categoryName : "Test"
}
But I need anotherlist to be encapsulated here. Iw ant below output
{
categoryId : 1,
categoryName : "Test"
subCategory:
{
name: ""
}
}
For subCategory attribute I have another class similar to SampleList.java. I can get the sub categories corresponding to each category. Can anyone help me out to get expected response?
I dont want to touch my SampleList class.
You have to extend your class SampleList
Class SampleList.java
public class SampleList {
private Integer categoryId;
private String categoryName;
private SubCategory subCategory;
//getter setter
And before you return your list of course you have to set the correct subCategory in your SampleList item.
If you don't want to spoil your SampleList class of course you could add a layer of DTO objects and map between them or manipulate the response directly e.g. with ResponseBodyAdvice
Approach : 1
public class SampleList
{
private Integer categoryId;
private String categoryName;
// Getter and Setter
}
public class SampleList2
{
private String name;
// Getter and Setter
}
// Logic to get the JSON value without mapping two different classes
private void getJsonValue() throws JsonProcessingException, JSONException
{
SampleList sampleList = new SampleList();
sampleList.setCategoryId(1);
sampleList.setCategoryName("cat 1");
String sampleListJson = new ObjectMapper().writeValueAsString(sampleList);
SampleList2 sampleList2 = new SampleList2();
sampleList2.setName("Sub category");
String valueOfSample2 = new ObjectMapper().writeValueAsString(sampleList2);
JSONObject sampleListJsonObj = new JSONObject(sampleListJson); // for class SampleList
JSONObject sampleList2JsonObj = new JSONObject(valueOfSample2); // for class SampleList2
sampleListJsonObj.put("subCategory", sampleList2JsonObj);
System.out.println(sampleListJsonObj.toString());
}
Approach : 2
public class SampleList
{
private Integer categoryId;
private String categoryName;
private SampleList2 subCategory;
// Getter and Setter
}
public class SampleList2
{
private String name;
// Getter and Setter
}
// Logic to get with mapping two classes as mentioned above
private static void getJsonValue() throws JsonProcessingException
{
SampleList sampleList = new SampleList();
sampleList.setCategoryId(1);
sampleList.setCategoryName("cat 1");
SampleList2 sampleList2 = new SampleList2();
sampleList2.setName("Sub category");
sampleList.setSubCategory(sampleList2);
String jsonString = new ObjectMapper().writeValueAsString(sampleList);
System.out.println(jsonString.toString());
}
Please let me know if you have any questions on the same.
Thank you.

List All Data Using Retrofit/OkHttp With Response List

I have some codes that fetch some data from my API. My question is how can I list all the objects that I fetched before without using this jsonData.get(0), I expect something like jsonData.get(i), so I assume using something like below, but I can't use it, so how can I do that? Thanks.
for (int i=0;i<jsonData.length();i++){
MainActivity.java
List<Promo> jsonData = response.body();
Log.i("TESTER",""+jsonData);
String promoID = jsonData.get(0).getId_promo();
String promoTipe = jsonData.get(0).getPromo_type();
String promoValue = jsonData.get(0).getValue_based();
String promoName = jsonData.get(0).getPromo_name();
With POJO class that looks like this
Promo.java
public class Promo {
#SerializedName("id_promo")
private String id_promo;
#SerializedName("promo_name")
private String promo_name;
#SerializedName("promo_type")
private String promo_type;
#SerializedName("value_based")
private String value_based;
#SerializedName("quota")
private String quota;
#SerializedName("id_event")
private String id_event;
#SerializedName("description")
private String description;
public String getId_promo() {
return id_promo;
}
public void setId_promo(String id_promo) {
this.id_promo = id_promo;
}
public String getPromo_name() {
return promo_name;
}
}
ApiUrl.java
#FormUrlEncoded
#POST("promopublic")
Call<List<Promo>> getPromo(
#Field("id_event") String id_event,
#Field("total_buyer") String totalBuyer,
#Field("id_user") String id_user,
#Field("id_ticket") String id_ticket);
Using for loop like below solved my problem
for (int i=0;i<jsonData.size();i++){}

How to convert List<Entity> to a string?

Here is the code :
I have a entity named ClassA which consists of following attribute
#JsonProperty("rowDeleted")
private Boolean rowDeleted;
#JsonProperty("start")
private List<Start> start = null;
#JsonProperty("end")
private List<End> end = null;
#JsonProperty("rows")
private List<Row> rows = null;
And Row is another entity which consists of attributes:
#JsonProperty("cells")
private List<Cell> cells = null;
#JsonProperty("clusteringKey")
private String clusteringKey;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
And Cell is another entity:
#JsonProperty("deleted")
private Boolean deleted;
#JsonProperty("name")
private String name;
#JsonProperty("value")
private String value;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
I am getting an object of ClassA and want to convert it into another entity which is ClassB contains fields:
private String end;
private String key;
private String keyspacename;
private String partitiondeleted;
private String rowdeleted;
private String rows;
private String start;
private String tablename;
private String triggerdate;
private String triggertime;
So basically i want to convert List rows of ClassA to String rows of ClassB.
Can anyone please suggest a way to do this.
Thanks in advance
suppose you have a list of class A.
List<A> list= . . . ;
List<B> newList=list
.stream()
.map(obj-> new B()
.setKey(obj.getKey())
.setKeyspacename(//set which field of class A will be saved)
.setPartitiondeleted()
// set more fields
)
.collect(Collecters.toList());
and then serialize this newlist into String by using jakson.
I wanted a string which could represent json format so modified my toString() as per my requirement and it solved my purpose.

Randomise an ArrayList<Object> in Java

Given that i have an arrayList of company objects. I want to shuffle the objects inside listcompanies. listcompanies has a list of object companies inside it. I want to shuffle the company objects inside the listcompanies arraylist.
This is my company object
public class Company {
private String id;
private String companyName;
private String currentTaskId;
private String task1_id;
private String task1_url;
private String task1_title;
private String task1_description;
private String task1_type;
private String task2_id;
private String task2_url;
private String task2_title;
private String task2_description;
private String task2_type;
private String task3_id;
private String task3_url;
private String task3_title;
private String task3_description;
private String task3_type;
private String task4_id;
private String task4_url;
private String task4_title;
private String task4_description;
private String task4_type;
private String task5_id;
private String task5_url;
private String task5_title;
private String task5_description;
private String task5_type;
}
This is how i store data:
//create a company ArrayList
ArrayList<Company> listcompanies = new ArrayList<>();
for(int i = 0 ; i < 60 ; i ++){
//Initialise a new company per iteration
Company company = new Company();
//store data
company.setcompanyName("Name: " + i);
company.setcompanycurrentTaskId(i+"");
listcompanies.add(company);
}
I tried doing this to shuffle listcompanies but it didn't work.
// I TRIED doing this for sorting the listcompanies
long seed = System.nanoTime();
Collections.shuffle(listcompanies, new Random(seed));
// nothing happened it did not sort the list of companies
My question was a little confusing. Though i already figured it out the shuffle method randomises the data when it's included in the arraylist. Thus it was random all along.

Categories