Java 8 sort multiple objects - java

public class B {
private String name;
private String value;
//Setters and Get
}
public class C {
private String name;
private String value;
//Setters and Get Methods
}
public class D {
private String name;
private String value;
//Setters and Get
}
public class A {
private B b;
private C c;
private D d;
// Setters and Get
}
public class Example{
List<A> a = new Array List<A>();
//Lets assume a will contain objects of class B, C and D
a .sort( Comparator.comparing(A::getB().getName).thenComparing(A::getC().getName));
}
Sort field from one pojo , then sort field by next pojo.
Need to understand how to sort in this situation. Can we use
Comparator.comparing ()in this case?

You can't use method refences like that, but you could just use lambda expressions:
a.sort(Comparator.comparing((A x) -> x.getB().getName())
.thenComparing(x -> x.getC().getName()));

Related

Grouping a list of main objects by their nested object's id

Given the following class A :
public class A {
private int id; //this field is unique
private int a_1; //this field ain't unique
private String a_2;
private String a_3;
//setters + getters
}
We can group a list of random objects of type A as follow by their respective a_1 :
Map<String, List<A>> sortedmap = list.stream()
.collect(Collectors.groupingBy(A::getA_1, Collectors.toList()));
Now given two classes B and C such as :
public class B{
private int id; //this field is unique for all entities of type B
private String b_1;
private C b_C; //many objects of type B may have a reference to the same object of type C
//setters + getters
}
public class C{
private int id; //this field is unique for all entities of type C
private String c_1;
private D c_D; //many objects of type C may have a reference to the same object of type D
//setters + getters
}
public class D{
private int id; //this field is unique for all entities of type D
private String d_1;
private String d_2;
//setters + getters
}
How can we sort a list of random objects of type B by their respective b_C.getC_D().getId() field?
You can group the results in a TreeMap which is ordered by default:
public static void main(String[] args) {
D d1 = new D();d1.setId(1);
D d2 = new D();d2.setId(2);
C c1 = new C();c1.setC_D(d1);
C c2 = new C(); c2.setC_D(d2);
B b1 = new B(); b1.setB_C(c1); b1.setId(1);
B b2 = new B(); b2.setB_C(c2); b2.setId(2);
B b3 = new B(); b3.setB_C(c2); b3.setId(3);
Map<String, List<B>> result = Arrays.asList(b1,b2,b3)
.stream()
.collect(Collectors.groupingBy(b -> ""+b.getB_C().getC_D().getId(),
TreeMap::new,
Collectors.toList()));
System.out.println(result);
}
The result is:
{1=[B [id=1]], 2=[B [id=2], B [id=3]]}
PS. #javaistaucheineinsel nice username ;)
I’d add custom getters to support this (not compiled, forgive typos):
public class B{
private int id; //this field is unique for all entities of type B
private String b_1;
private C b_C; //many objects of type B may have a reference to the same object of type C
//setters + getters
public int getBCDId() {
return b_C.getCDId();
}
}
public class C{
private int id; //this field is unique for all entities of type C
private String c_1;
private D c_D; //many objects of type C may have a reference to the same object of type D
//setters + getters
public int getCDId() {
return c_D.getId();
}
}
Now you can sort and/or group B objects by the value they return from their getBCDId methods. Just like you would do for B’s own attributes.

ModelMapper: Map object which has nested collection to flat object

I have a class with a nested list and I want to map this object into list of flat objects using ModelMapper.
public class A {
private String str;
private String str2;
private List<B> blist;
// Setters and getters
}
public class B {
private String str3;
private String str4;
// Setters and getters
}
public class C {
private String str;
private String str2;
private String str3;
private String str4;
// Setters and getters
}
I want to convert an object of class A into a list of objects of class C

Creating JSON by combining fields from two classes

I have two classes : class A , class B
class A{
private int F1;
private String F2;
}
class B{
private int F3;
private String F4;
private String F5;
}
I want a JSON like this:
{
"F1": 123
"F2": "ABC"
"F3": 456
"F4": "CDE"
"F5": "FGH"
}
I am using springboot which creates JSON as soon as I return object from #RestController. How can I achieve the above json using these two classes.
Note :
1.) I already know that by using class A extends B , I can achieve
this but I am looking for some spring based method to achieve this
2.) Using #Embeddable in class B & then creating reference in Class A creates
additional tag B in JSON as shown :
{
"F1": 123
"F2": "ABC"
b: {
"F3": 456
"F4": "CDE"
"F5": "FGH"
}
}
How about using jackson #JsonUnwrapped?
http://fasterxml.github.io/jackson-annotations/javadoc/2.0.0/com/fasterxml/jackson/annotation/JsonUnwrapped.html
public class A{
#JsonUnwrapped
private B b;
public User getB() ...
}
Create a delegating class AB:
public final class AB {
private final A a;
private final B b;
public AB(A a, B b) {
this.a = a;
this.b = b;
}
// Delegation methods to A
public int getF1() { return this.a.getF1(); }
public String getF2() { return this.a.getF2(); }
// Delegation methods to B
public int getF3() { return this.b.getF3(); }
public String getF4() { return this.b.getF4(); }
public String getF5() { return this.b.getF5(); }
}

How to pass different objects (having same parent) to a constructor and how to identify type of that object in constructor

I have a scenario where I'm sending different objects to a constructor and I have to identify the class of that object and set values accordingly.
Class ABC {
private long id;
private SomeClass obj;
private String xyzName;
private Date date;
private EnumType status;
// And Getters and Setters
}
Class A extends ABC {
private String someOtherId;
private String type;
private String model;
private String manufacturer;
//and some props and Getters and Setters
}
Class B extends ABC {
private String someOtherId;
private String equipName;
private String model;
private String serialNo;
//and some props and Getters and Setters
}
Class C extends ABC {
private String someOtherId;
private String materialName;
private String desc;
private String serialNo;
//and some props and Getters and Setters
}
Note: These are the entity classes
And In Controller, I'm doing ops like adding, editing, updating(mostly changing statuses) and etc.And every time I do I have to enter or log kind of msg into
History Class. something like
From AController
historyService.enterLogToHistory(new
History(Aobject, EnumType.somestatus));
From BController,
historyService.enterLogToHistory(new History(Bobject,
EnumType.somestatus));
From CController,
historyService.enterLogToHistory(new
History(Cobject,EnumType.somestatus));
Class History() {
private long id;
private Date date;
private String Status;
private String Activity; // or msg
// some other #Transient properties
History(Object obj) {
//set above values like by getting values form this obj(using getters)
}
History(Object obj, EnumType status) {
this(obj);
// set some other #Transient properties by getting values form this obj
// and set value for msg;
}
}
So, Now my problem is how to identify that object whether it is A obj,
B, obj or C obj because if know the type of object only I can the getters of that obj and I can set values in History constructor.
So, please anyone help me out in this
To get rid of instanceof mess, consider using oveloaded constructors:
class History {
History(A a) {
// initialize by `A` instance
}
History(B b) {
// initialize by `B` instance
}
//...
}
This will work if you know classes of all instances on compile time.
Another option is to switch to static factory methods:
public class History {
// private constructor to hide instance creation
private History(ABC abc) {
this.id = abc.getId();
this.date = new Date(abc.getDate().getTime());
// ... another common properties
}
public History setStatus(Status s) {
this.status = s;
return this;
}
// public static factory methods to create instances specified by input
public static History of(A a) {
History h = new History(a);
h.type = a.getType();
// ... properties specific for `A`
return h;
}
public static History of(A a, Status status) {
return of(a).setStatus(status);
}
public static History of(B b) {
History h = new History(b);
h.model = b.getModel();
// ... properties specific for `B`
return h;
}
// ...
}
Then, to create History instances, caller invokes:
History aHistory = History.of(a);
History bHistory = History.of(b, Status.ACTIVE);
The main advantage of such approach is that more stable API is introduced, while it remains flexible for internal refactoring. Imagine, you decide to implement various behavior for History of different types, e.g. VehicleHistory and VesselHistory. So you create those classes extending History, override some methods in them and refactor a few of() methods in History class (so that not new History(), but new VehicleHistory() is called). As far as you never call constructor externally, for outer code things remain unchanged -- it receives History object as before from the same History.of() method as before.

Best container for <Key, <pairOfType1,pairOfType2>>

I'm wondering what the best java like container would it be for
<Key, <pairOfType1,pairOfType2>>
I have an object1 that is the key and a t1 and t2.
My classes have the fallowing attributes:
public class Patient implements Externalizable {
protected int iD;
protected String name;
protected String CNP;
protected int age;
public class Treatment implements Externalizable {
protected int iD;
protected String description;
public class Diagnosis implements Externalizable {
protected int iD;
protected String name;
protected String description;
protected String date;
PS: I curious for a 'real program' since my requirements are to wasve.
I have considered the idea of
private Map<Patient, <Diagnosis, Treatmet>> map = new Map<>();
How about a Map<Patient, Pair<Diagnosis, Treatment>> ?
The pair class could look like:
public class Pair<T, U> {
private final T t;
private final U u;
public Pair(T t, U u) {
this.t = t;
this.u = u;
}
//getters
}
Why can't you just put your Diagnosis and Treatment in a class and pass
Pair<Diagnosis,Treatment> pair = new Pair<>(d,t);
Map<Key, Pair> map = new Map<>();
...
where
class Pair<D,T> {
public D myD;
public T myT;
public Pair(D d, T t) {
myD = d;
myT = t;
}
}
A Dictionary or a Map supports this Key,Value lookup.
In your object model you wouldn't have a t1 and a t2, you instead would have a class like this:
public class ExternalizableContainer
{
private Externalizable t1;
private Externalizable t2;
public ExternalizableContainer(Externalizable t1,Externalizable t2)
{
this.t1=t1;
this.t2=t2;
}
}
I would create a separate object that contains your two values.
class MyObject {
String val1;
String val2;
...
}
and then create a map with MyObject as the value. This assumes that the two values you want to store are Strings. #assylias gives a more generic approach by typing the class
new HashMap<Key, MyObject>();

Categories