Using an equals method is definitely the way to go. You don't have to write it yourself. Your IDE can generate it, or you can use a tool like Lombok to generate it at compile time. The latter has the advantage of automatically updating if fields are added or removed.
Answer from user8681 on Stack OverflowUsing an equals method is definitely the way to go. You don't have to write it yourself. Your IDE can generate it, or you can use a tool like Lombok to generate it at compile time. The latter has the advantage of automatically updating if fields are added or removed.
Since you are only checking the equality of the data, I wouldn't recommend overriding equals.
This is typically used to determine object equality, which is a slightly different context.
Just create a separate procedure.
An optimal approach, considering the database will have numerous values, would be to create a class to implement the procedure.
This will allow for the re-use of the variables during iterative invocations, thus reducing memory consumption.
In this example I created a class, UserEventUtil, with a single method, checkEquality.
It utilizes reflection to compare the opposing fields.
This should improve the scalability, and hence remove the requirement to explicitly type every field.
If you have any objects other than the basic scalar types here, you can just add them to the if-conditional checks, utilizing whatever data they may have to prove equality.
import java.lang.reflect.Field;
public class UserEventUtil {
UserEvent userEventA, userEventB;
Field[] fieldsA, fieldsB;
Field fieldA, fieldB;
Class<?> type;
String stringA, stringB;
int index;
public UserEventUtil(UserEvent userEventA, UserEvent userEventB) {
this.userEventA = userEventA;
this.userEventB = userEventB;
}
boolean checkEquality() throws IllegalAccessException {
fieldsA = userEventA.getClass().getDeclaredFields();
fieldsB = userEventB.getClass().getDeclaredFields();
for (index = 0; index < fieldsA.length; index++) {
fieldA = fieldsA[index];
fieldB = fieldsB[index];
type = fieldA.getType();
if (type == String.class) {
stringA = (String) fieldA.get(userEventA);
stringB = (String) fieldB.get(userEventB);
if (stringA == null && stringB == null) continue;
if (stringA == null || stringB == null) return false;
else if (!stringA.equals(stringB)) return false;
} else if (type == int.class) {
if (fieldA.getInt(userEventA) != fieldB.getInt(userEventB))
return false;
} else if (type == float.class) {
if (fieldA.getFloat(userEventA) != fieldB.getFloat(userEventB))
return false;
}
}
return true;
}
}
And, to simulate the UserEvent class, I created a basic object with some bunk fields.
class UserEvent {
String valueA, valueB, valueC;
int valueD, valueE, valueF;
float valueG, valueH, valueI;
}
Here is an example of comparing three separate values.
UserEvent userEventA = new UserEvent();
userEventA.valueA = "a";
userEventA.valueB = "b";
userEventA.valueC = "c";
userEventA.valueD = 1;
userEventA.valueE = 2;
userEventA.valueF = 3;
userEventA.valueG = 4.5f;
userEventA.valueH = 6.7f;
userEventA.valueI = 8.9f;
UserEvent userEventB = new UserEvent();
userEventB.valueA = "a";
userEventB.valueB = "b";
userEventB.valueC = "c";
userEventB.valueD = 1;
userEventB.valueE = 2;
userEventB.valueF = 3;
userEventB.valueG = 4.5f;
userEventB.valueH = 6.7f;
userEventB.valueI = 8.9f;
UserEvent userEventC = new UserEvent();
userEventC.valueA = null;
userEventC.valueB = "b";
userEventC.valueC = "c";
userEventC.valueD = 1;
userEventC.valueE = 2;
userEventC.valueF = 3;
userEventC.valueG = 4.5f;
userEventC.valueH = 6.7f;
userEventC.valueI = 8.9f;
UserEventUtil util;
util = new UserEventUtil(userEventA, userEventB);
System.out.println("util.checkEquality(), userEventA and userEventB = " + util.checkEquality());
util = new UserEventUtil(userEventB, userEventC);
System.out.println("util.checkEquality(), userEventB and userEventC = " + util.checkEquality());
Output
util.checkEquality(), userEventA and userEventB = true
util.checkEquality(), userEventB and userEventC = false
Override the toString() method in your pojo class like below
@Override
public String toString() {
return "brand: " + this.brand + ",color: " + this.color;
}
car1.toString().equals(car2.toString()); //It will return true if both objects has same values
In case you have large nos of parameter i will suggest you to go with bellow code
public static boolean comparePOJO(Object obj1, Object obj2) {
return new Gson().toJson(obj1).equals(new Gson().toJson(obj2));
}
comparePOJO(car1,car2); //It will return true
This type of reflection is built into Hamcrest as SamePropertyValuesAs, which compares bean-named properties (getFoo, isBar) instead of the fields that likely power them. Core Hamcrest support is built into JUnit, so you'd just need to add the Hamcrest library that includes the SamePropertyValuesAs matcher.
assertThat(car1, samePropertyValuesAs(car2));
This may be an option:
Map<String, Employee> map = employees.stream()
.collect(groupingBy(
Employee::name,
collectingAndThen(
reducing((a, b) -> a.date.isAfter(b.date) ? a : b),
Optional::get
)
));
This is what happens:
First, we group by name, which results in a name => list[date] mapping. Then we reduce the list to get a single value, comparing each element of the list with dates to the subsequent one. The comparison is done with isAfter.
The collectionAndThen(…, Optional::get) part exists because reducing returns an Optional<E> rather than an E. But groupingBy guarantees us that each list contains at least one element.
In order to execute this operation you have to follow these steps:
- group by names having a
Map<String, List<Employee>>as a result - reduce every
List<Employee>to oneEmployee - select the employee that has the max date
Map<String, Optional<Employee>> mapResult = employees.stream()
.collect(
Collectors.groupingBy(Employee::getName, // 1
Collectors.reducing( // 2
BinaryOperator.maxBy(Comparator.comparing(Employee::getDate)) // 3
)
)
);
Example input:
["John", 2022-02-07]
["John", 2022-02-17]
["Mike", 2022-01-19]
["Mike", 2022-03-17]
Example output:
["John", 2022-02-17]
["Mike", 2022-03-17]
You would do something like this:
Map<String, B> bById = ...
Map<String, B> bByName = ...
for (A a : listA) {
B b = bById.getOrDefault(a.id, bByName.get(a.name));
if (b != null) {
a.setPersonalDetails(b.getPersonalDetails);
}
}
you can use comparator to achieve this.Just a example psudo code is given below
Collections.sort(listA, Comparator.comparing(A::getId)
.thenComparing(A::getName)
.thenComparing(A::getAge));
Using anonymous inner class, Comparator and Collections.sort():
Collections.sort(palyers, new Comparator(){
public int compare(Object o1, Object o2){
player p1 = (player) o1;
player p2 = (player) o2;
return p1.getPoints().compareTo(p2.getPoints());
}
});.
So you want to know the pair of players whose score has the smallest difference? I don't think there's an API function for that, although there might be something in the Apache Commons Collections.
Otherwise you'll have to use a nested loop.
int res1 = -1, res2 = -1;
int maxDiff = Integer.MAX_VALUE;
for ( int i = 0; i < players.size( ); i++ )
{
for ( int j = i + 1; j < players.size() ; j++ )
{
int diff = Math.abs( players.get(i).getPoints( ) - players.get(j).getPoints( ) );
if ( diff < maxDiff )
{
maxDiff = diff;
res1 = i;
res2 = j;
}
}
}
System.out.println(players.get(res1).getPlayerName( ) + " and " + players.get(res2).getPlayerName( ));
Obviously, this code needs some work; for example, if two pairs of players have the same difference between them, only the latest pair processed will be reported. You may also want to re-work this piece of code to remove the default values (Note how the System.out.println will crash if your List contains 0 players, for example). I leave these for you to solve. HTH.