Compare objects and create a new one similar to one of them - java

I want to compare 2 objects and create a new one with the values of the second if its values are not null. Otherwise the values of the first one should be copied to the object created.
My problem is that I don't know how to set the value which I want to copy. I know that to get the name of the attribute I can use field.getName(), but how can I do the set of that attribute on the new object?
Example:
Test t1 = new Test();
t1.name = "Maria";
t1.age = 30;
t1.street = "somewhere";
Test t2 = new Test();
t2.name = "Maria";
t2.age = ;
t2.street = "here and here";
Test resultIwant = new Test();
t2.name = "Maria";
t2.age = 30;
t2.street = "here and here";
Code:
Test resultIwant = new Test(t2);
for(Field field : t1.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object value1= field.get(t1);
Object value2= field.get(t2);
if ((value2 == null && value1 == null) || (value2 == value1))
continue;
else {
if(value2 != null && value1 == null)
continue;
else if(value2 == null && value1 != null) {
resultIwant.set???? = value1; <----------- this is my problem
}
}
}

The Java Reflection API not only allows you to read but also to set a field value.
In your code you can try the following:
Test resultIwant = new Test(t2);
for(Field field : t1.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object value1= field.get(t1);
Object value2= field.get(t2);
if ((value2 == null && value1 == null) || (value2 == value1))
continue;
else {
if(value2 != null && value1 == null)
continue;
else if(value2 == null && value1 != null) {
String fieldName = field.getName();
Field fieldOnResultIwant =
resultIwant.getClass().getDeclaredField(fieldName);
fieldOnResultIwant.setAccessible(true);
// Honestly, I do not remember... Perhaps also will work:
// field.set(resultIwant, value1);
fieldOnResultIwant.set(resultIwant, value1);
}
}
}
I posted a more complete, but related, answer here.

Related

how to avoid multiple if-else statements for vaildation in Java

I have lots of multiple if-else statements. For code optimization, I need to write one function for all if else logic. As of now my code structure is in below.
input request is in JSONObject(org.json.simple.JSONObject), which have more than 10 values.
String s = (String) inputObj.get("test");
String s1 = (String) inputObj.get("test");
String s2 = (String) inputObj.get("test");
String s3 = (String) inputObj.get("test");
if (s != null && s.trim().isEmpty()) {
if (s1 != null && s1.trim().isEmpty()) {
if (s2 != null && s2.trim().isEmpty()) {
if (s3 != null && s3.trim().isEmpty()) {
if (s4 != null && s4.trim().isEmpty()) {
........
} else {
return;
}
} else {
return;
}
} else {
return;
}
} else {
return;
}
} else {
return;
}
How to avoid this kind of looping and throw an error message in common method.
Advance thanks.
Consider adding all your strings to array or ArrayList of string, and looping thru each entry in it, and check them for null or emptiness.
You can try this.
void main() {
List<String> sList = new ArrayList<>();
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
for(String s : sList){
try {
checkString(s);
}catch (Exception e){
//log or print the exception, however you like
}
}
}
void checkString(String s) throws Exception{
if(s!= null && !s.trim().isEmpty()){
//doStuff
}else{
throw new Exception("String is null or empty !!!");
}
}
You should also check this out.
public class YourClass{
private boolean isBlankDataPresent(JSONObject inputObj, String[] keys) throws Exception {
for (String key : keys) {
String input = (String) inputObj.get(key);
if( input == null || input.trim().isEmpty())
throw new Exception(key +" is Empty");
}
return false;
}
public boolean validateData(JSONObject inputObj, String[] keys) throws Exception {
boolean isBlankDataPresent= isBlankDataPresent(inputObj, keys);
if (!isBlankDataPresent) {
// do Your Stuff and return true
}
}
}
public Integer checkIsEmapty(String checkingString){
if(checkingString != null && !checkingString.trim().isEmpty()){
return 1;
}
return 0;
}
public String method(){
String s ="";
String s1 = "hi";
String s2 = "java";
String s3 = null;
String s4 = null;
Integer s1i = checkIsEmapty(s);
Integer s2i = checkIsEmapty(s1);
Integer s3i = checkIsEmapty(s2);
Integer s4i = checkIsEmapty(s3);
Integer s5i = checkIsEmapty(s4);
Integer total = s1i + s2i + s3i + s4i + s5i;
switch (total){
case 1 :
// To DO
case 2 :
// To DO
}
}
in switch used to checking the value, U can pass binary and Integer also
Like #Emre Acre mentioned,
List<String> sList = new ArrayList<>();
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
sList.add(inputObj.get("test"));
boolean allDataValid = sList
.stream()
.allMatch(s -> s != null && s.trim().isEmpty());
if(allDataValid) {
......
} else {
return;
}

Collections comparator with null at the end

I have some User objects that can have name and email, I want them sorted by name , then by email, but firstly show users that have not null names. I was trying like so:
Collections.sort(usersList, new Comparator<User>() {
#Override
public int compare(User obj1, User obj2) {
int res = 0;
//to make sure null names at the end
if (obj1.getFullName() == null && obj2.getFullName() == null)
res = 0;
if (obj1.getFullName() == null)
res = 1;
if (obj2.getFullName() == null)
res = -1;
//logic for name sorting then email sorting
if (obj1.getFullName() != null && obj2.getFullName() != null)
res = obj1.getFullName().compareTo(obj2.getFullName());
if (res == 0)
res = obj1.getEmail().compareTo(obj2.getEmail());
return res;
}
});
As result I get names first but sorted by email not by name.
This can be easily done with Java-8's Comparator utilities:
List<User> users = Arrays.asList(new User("pete", "pete#email"), new User(null, null), new User("alex", null), new User(null, "email"));
Collections.sort(users, Comparator.comparing(User::getName, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(Comparator.comparing(User::getEmail, Comparator.nullsLast(Comparator.naturalOrder()))));
System.out.println(users);
Output:
[
User{name='alex', email='null'},
User{name='pete', email='pete#email'},
User{name='null', email='email'},
User{name='null', email='null'}
]

java compare multiple values and find best match

I need to find best matched employee salary in the DB records as:
Name: City: State:
A (null) (null)
A (null) DEL
(null) (null) (null)
A SAKET DEL
Match order should be:
1. NAME = name, STATE = state, CITY = city
2. NAME = name, STATE = state , CITY = NULL
3. NAME = name, STATE = NULL, CITY = NULL
4. NAME = NULL, STATE = NULL, CITY = NULL
Means if in a row where all attributes matches – it should be selected, if we do not have that kind of data we should go to next best option like select state and city as NULL, etc.
My code as below, is giving me correct results but I need a more efficient way.
private static BigDecimal getsalaryForBestMatch(ResultSet results, EmployeeRq request) throws Exception{
BigDecimal salary = null;
BigDecimal salaryWithState = null;
BigDecimal salaryWithName = null;
BigDecimal salaryWithNoMatch = null;
while (results.next()) {
String billerName = results.getString("EMP_NAME") != null ? results.getString("EMP_NAME").trim() : null;
String city = results.getString("CITY") != null ? results.getString("CITY").trim() : null;
String state = results.getString("STATE") != null ? results.getString("STATE").trim() : null;
BigDecimal salaryRslt = null;
if(results.getString("SALARY") != null){
salaryRslt = BigDecimal.valueOf(results.getDouble("SALARY"));
}
if(billerName != null && !billerName.equals("") && billerName.equals(request.getBillPaymentsalaryCalculateInfo().getBillerName())){
if(city != null && !city.equals("") && city.equals(request.getMsgRqHdr().getCity()) &&
state != null && !state.equals("") && state.equalsIgnoreCase(request.getMsgRqHdr().getstate())){
salary = salaryRslt;
break;
} else if((city == null || city.equals("")) && state != null && !state.equals("") &&
state.equalsIgnoreCase(request.getMsgRqHdr().getState())){
salaryWithState = salaryRslt;
} else if((city == null || city.equals("")) && (state == null || state.equals(""))){
salaryWithName = salaryRslt;
}
} else if((billerName == null || billerName.equals("")) && (city == null || city.equals("")) &&
(state == null || state.equals(""))){
salaryWithNoMatch = salaryRslt;
}
}
if(salary != null){
return salary;
} else if(salaryWithState != null){
salary = salaryWithState;
} else if(salaryWithName != null){
salary = salaryWithName;
} else if(salaryWithNoMatch != null){
salary = salaryWithNoMatch;
}
return salary;
}
EDIT: I dont want to use 3 extra variables: salaryWithState, salaryWithName, salaryWithNoMatch.
I want just to give the general idea how this can be implemented, so I haven't actually tested and checked if it will give you the right salary.
public BigDecimal getSalaryForBestMatch(ResultSet resultSet, PaymentSalaryInfo paymentSalaryInfo) {
Map<String, Supplier<String>> m1 = new HashMap<>();
m1.put("EMP_NAME", paymentSalaryInfo::getBillerName);
m1.put("STATE", paymentSalaryInfo::getState);
m1.put("CITY", paymentSalaryInfo::getCity);
Map<String, Supplier<String>> m2 = new HashMap<>();
m2.put("STATE", paymentSalaryInfo::getState);
m2.put("CITY", paymentSalaryInfo::getCity);
Map<String, Supplier<String>> m3 = new HashMap<>();
m3.put("CITY", paymentSalaryInfo::getCity);
Optional<String> salary = Optional.empty();
while(resultSet.next() && !salary.isPresent()) {
salary = apply(m1, resultSet);
//check salary and then apply(m2, resultSet) ....
}
return salary.isPresent() ? new BigDecimal(salary.get()) : null;
}
public Optional<String> apply(Map<String, Supplier<String>> filter, ResultSet resultSet) {
boolean allMatch = filter.entrySet().stream().allMatch(entry -> {
String value = resultSet.getString(entry.getKey());
return value != null && value.equals(entry.getValue().get());
});
return allMatch ? Optional.of(resultSet.getString("salary")) : Optional.empty();
}
I have written the same logic in a different way with using arrays. If your environment can afford to use arrays, you can use this code. But I have not tested the code.
private static BigDecimal getsalaryForBestMatch(ResultSet results, EmployeeRq request) throws Exception{
BigDecimal salary = null;
int matchCount = 0;
String rBillerName = request.getBillPaymentsalaryCalculateInfo().getBillerName();
String rCity = request.getMsgRqHdr().getCity();
String rState = request.getMsgRqHdr().getstate();
String [] truthArray = new String[] {rBillerName, rCity, rState};
while (results.next()) {
String billerName = results.getString("EMP_NAME") != null ? results.getString("EMP_NAME").trim() : null;
String city = results.getString("CITY") != null ? results.getString("CITY").trim() : null;
String state = results.getString("STATE") != null ? results.getString("STATE").trim() : null;
BigDecimal salaryRslt = results.getString("SALARY") != null ? BigDecimal.valueOf(results.getDouble("SALARY")): null;
String [] testArray = new String[] {billerName, city, state};
int localMatchCount = 0;
for(int i = 0; i < testArray.length; i++) {
if(testArray[i] != null && testArray[i].equals(truthArray[i]))
localMatchCount++;
else {
break;
}
}
if(localMatchCount >= matchCount){
matchCount = localMatchCount;
salary = salaryRslt;
}
}
return salary;
}

Check if all values in a map are equal

I need to check if all values in a map are equal. I have a method to perform this task but would like to use a library or native methods. Limitations: Java 5 + Apache Commons libraries.
public static boolean isUnique(Map<Dboid,?> aMap){
boolean isUnique = true;
Object currValue = null;
int iteration = 0;
Iterator<?> it = aMap.entrySet().iterator();
while(it.hasNext() && isUnique){
iteration++;
Object value = it.next();
if(iteration > 1){
if (value != null && currValue == null ||
value == null && currValue != null ||
value != null && currValue != null & !value.equals(currValue)) {
isUnique = false;
}
}
currValue = value;
}
return isUnique;
}
What about this something like this:
Set<String> values = new HashSet<String>(aMap.values());
boolean isUnique = values.size() == 1;
how about
return (new HashSet(aMap.values()).size() == 1)
I know the original questions asks for solutions in Java 5, but in case someone else searching for an answer to this question is not limited to Java 5 here is a Java 8 approach.
return aMap.values().stream().distinct().limit(2).count() < 2
You could store the values in a Bidirectional Map and always have this property.
public static boolean isUnique(Map<Dboid,?> aMap) {
Set<Object> values = new HashSet<Object>();
for (Map.Entry<Dboid,?> entry : aMap.entrySet()) {
if (!values.isEmpty() && values.add(entry.getValue())) {
return false;
}
}
return true;
}
This solution has the advantage to offer a memory-saving short cut if there are many differences in the map. For the special case of an empty Map you might choose false as return value, change it appropriately for your purpose.
Or even better without a Set (if your Map does not contain null-values):
public static boolean isUnique(Map<Dboid,?> aMap) {
Object value = null;
for (Object entry : aMap.values()) {
if (value == null) {
value = entry;
} else if (!value.equals(entry)) {
return false;
}
}
return true;
}
As my comment above:
//think in a more proper name isAllValuesAreUnique for example
public static boolean isUnique(Map<Dboid,?> aMap){
if(aMap == null)
return true; // or throw IlegalArgumentException()
Collection<?> c = aMap.getValues();
return new HashSet<>(c).size() <= 1;
}

Multiple inserts during concatenation?

I've a JSONObject that I've converted to a JSON array then parsed it further to its separate strings. I've concatenated these to form one new string. Here is the code that I've used.
for(int n = 0; n<newtrs_array.length();n++){
JSONObject object = newtrs_array.getJSONObject(n);
String newcompanyid = object.getString("companyid");
String newusername = object.getString("username");
String newdate = object.getString("date");
String newClientId = object.getString("clientid");
String newprojectId = object.getString("projectid");
String newniv1 = object.getString("niv1");
String newniv2 = object.getString("niv2");
String newworktypeid = object.getString("worktypeid");
String newtimetypeid = object.getString("timetypeid");
String newhours = object.getString("hours");
String newcomment = object.getString("comment");
String newprivatecomment = object.getString("privatecomment");
String newopen = object.getString("open");
String newreportid = object.getString("reportid");
newtrsArray += newcompanyid+"#"+newusername+"#"+newdate+"#"
+newClientId+"#"+newprojectId
+"#"+newniv1+"#"+newniv2+"#"+newworktypeid
+"#"+newtimetypeid+"#"+newhours+"#"+newcomment
+"#"+newprivatecomment+"#"+newopen+"#"+newreportid;
}
}
This is the code that is used to split the newtrsarray
for(int n=0; n<split_frombufferedValue.length; n++){
if(split_frombufferedValue[n] != null){
try{
//Log.i(TAG, "***********%%%%%%%%%"+split_frombufferedValue[1]);
newtrsArray = split_frombufferedValue[0].toString();
newschemaArray = split_frombufferedValue[1].toString();
Log.i(TAG, "************* "+newschemaArray);
newdeletedtrsArray = split_frombufferedValue[2].toString();
String newcreatedtrs_array = split_frombufferedValue[3].toString();
String newsync_reponse = split_frombufferedValue[4].toString();
String newmodtrs_array = split_frombufferedValue[5].toString();
} catch(Exception e){
e.printStackTrace();
}
}
}
split_newtrsArray = newtrsArray.split("#");
split_newdeletedtrsArray = newdeletedtrsArray.split("####");
split_newschemaArray = newschemaArray.split("%%%%");
Log.i(TAG, "############# "+split_newtrsArray[0]+" -length "+split_newtrsArray.length);
}
My PROBLEM is that: newtrsarray is about 4000chars or more in size. This is causing the "#" to be inserted twice or even thrice at times. As shown below
&&--Second activty:HTTPClient--**(824): !!!!!------UTB17#DA#2011-10-10#1000#363636#10##105#30#5###no#30667UTB17#DA#2011-09-12#1000#363636#10##100##6##Not Available#yes#31659UTB17#DA#2011-09-13#1000#363636#10##100##2###yes#31665
How can I work around this problem. The values must be concatenated to one string and then split at an another function. These must be then inserted into a database. Hope I was able to explain my problem clearly.
Cheers !
I think your problem comes when you are inserting it again which is when the array has a null element check out an if statement and check if its null or not. Do it as so:
if(newcompanyid.equals("") || newcompanyid == null || newusername.equals("") || newusername == null
|| newdate.equals("") || newdate == null || newClientId.equals("") || newClientId == null ||
newprojectId.equals("") || newprojectId == null || newniv1.equals("") || newniv1 == null ||
newniv2.equals("") || newworktypeid.equals("") || newworktypeid == null ||newtimetypeid.equals("")
|| newtimetypeid == null || newhours.equals("") ||newhours == null ||newcomment.equals("")
||newcomment == null ||newprivatecomment.equals("") ||newprivatecomment == null||newopen.equals("")
||newopen == null||newreportid.equals("") || newreportid == null)

Categories

Resources