I have a List of ProcessedClass (POJO I have created) that I would like to generate to a string of comma-delimited values. So all items in the list output to a single, comma-delimited list.
My plan is to: pass the list into a method, iterate through the list and append commas and finally remove the last comma and return the resulting string. The object being processed will have some nested POJO's with multiple different variable types (string, int, boolean, other POJO's, LocalDate etc..). I have added an example of the structure below.
My question is what is the best way to go about constructing this? Thank you in advance.
Example structure being processed:
//List<ProcessedClass> will be passed into the iternation method
public class ProcessedClass {
private Other other;
private Info info;
}
public class Other {
private String stringMessage;
private boolean booleanValue;
...
}
public class Info {
//Another defined POJO
private User user;
private LocalDate date;
private String name;
...
}
You can use StringJoiner with , delimiter.
StringJoiner stringJoiner = new StringJoiner(",");
processedClasses.forEach(a -> stringJoiner.add(a.toString()));
System.out.println(stringJoiner);
Of course, you have to implement the toString method in all defined classes.
Related
I need to transform an array of one type to an array of another type.
More specifically, I need to pull just a couple fields from each object in the starting array to create the resulting array, which will contain only those 2 fields, though named differently.
For example, let's say I have an array of Thing objects:
public class Thing {
private String id;
private String description;
... // other fields
}
I need to create from that an array of Item objects:
public class Item {
private String code;
private String data;
...
}
... where the id from each Thing becomes code in each Item; and description becomes data.
I've seen examples of using the Stream api to transform an array of objects to an array of Strings. But it's unclear to me thus far how to transform an object to another object.
Try this.
record Thing(String id, String description) {}
record Item(String coded, String data) {}
public static void main(String[] args) {
Thing[] array = {new Thing("1", "one"), new Thing("2", "two")};
Item[] transformed = Arrays.stream(array)
.map(thing -> new Item(thing.id(), thing.description()))
.toArray(Item[]::new);
System.out.println(Arrays.toString(transformed));
}
output:
[Item[coded=1, data=one], Item[coded=2, data=two]]
I want to write a generic function that accepts two objects of same entity class and compares the fields that are different and returns List of all the changes made to particular fields along with time.
One among the many entity classes would be say Member as follows
public class Member {
String firstName;
String lastName;
String driverLicenseNumber;
Integer age;
LocalDateTime timestamp;
}
In the DB, I have a table called member_audit that gets populated with old data whenever there is a change in member table using triggers (Similarly for other entities).
The List of resource for each of the entity I would be returning is something like
public class MemberAuditsResource {
private String field;
private LocalDateTime on;
private String changeType;
private String oldValue;
private String newValue;
}
I can only think of writing a function for each entity separately like this
private List<MembeAuditsResource> memberCompare(Member obj1, Member obj2) {
//Compare every field in both the objects using if else and populate the resource.
}
And then calling the above function to compare every pair of record in the entity_audit table.
The code would be very large to compare every field and multiplied by different entities.
Is there a better and efficient way?
If you extend the ideas to compare the object graph , it is not a trivial problem. So, the efficient way is not to re-inventing the wheel but use an existing library such as JaVers :
Member oldMember = new Member("foo" ,"chan" ,"AB12" , 21 ,LocalDateTime.now());
Member newMember = new Member("bar" ,"chan" ,"AB12" , 22 ,LocalDateTime.now());
Diff diff = javers.compare(oldMember, newMember);
for(Change change: diff.getChanges()) {
System.out.println(change);
}
Then , you can get something like:
ValueChange{ 'firstName' changed from 'foo' to 'bar' }
ValueChange{ 'age' changed from '21' to '22' }
Convert both object to a Map using JSON objectMapper.convertValue method. Then you can easily compare the keys/values of the two maps and create a list of differences.
I have one java class like below:
public class Location
{
public String city;
public String state;
public String country;
public enum type{Beach,Forest,Hills,Desert};
}
as above type member is enum type and i want to assign multiple enum values to type proprties like one Location object has more then one type properties like it has Hills as well as Forest.
then how should i have to do it?
where to declare enum and how to assign to enum values to one object.
Is it possible to assign to enum values one object without using array?
You need a Collection to store a variable number of values. Since you don't want to have duplicates use a Set. For enums exist java.util.EnumSet which has a compact and efficient way to store multiple values:
public class Location
{
public enum Type {Beach,Forest,Hills,Desert};
public String city;
public String state;
public String country;
public EnumSet<Type> types = EnumSet.noneOf(Type.class); // start with empty set
}
You can store them in class variables:
private final Terrain first = Terrain.BEACH;
private final Terrain second = Terrain.DESERT;
Similarly, you can store them in a collection of terrains if that is more appropriate:
private final Set<Terrain> terrains = new HashSet<>(Arrays.asList(Terrain.BEACH, Terrain.DESERT));
Or use an EnumSet:
private final EnumSet<Terrain> terrains = EnumSet.of(Terrain.BEACH, Terrain.DESERT);
On a side note, it is more conventional to declare enumerations in their own file, I have assumed that it will be called Terrain. Also, constants (thus also enum values) are usually written in capital letters.
I have a list from some complex type and I want to figure a neat way to construct a list only from one of its fields using Java 8's streams. Let's take as an example:
public static class Test {
public Test(String name) {
this.name = name;
}
public String getName() {
return name;
}
private String name;
// other fields
}
And imagine that I have a List<Test> l;. Now I want to create a new list that contains the values of name of all elements in l. One possible solution that I found is the following:
List<String> names = l.stream().map(u ->u.getName()).
collect(Collectors.<String> toList());
But I was wondering if there is a better way to do this - map a list of a given type to another list of different type.
Using method references is shorter :
List<String> names = l.stream().map(Test::getName).
collect(Collectors.toList());
You can't avoid at least two Stream methods, since you must first convert each Test instance to a String instance (using map()) and then you must run some terminal operation on the Stream in order to process the Stream pipeline (in your case you chose to collect the Stream of Strings into a List).
I have a SearchCriteria POJO class
public class SearchCriteria{
private int empId;
private String empName;
private String empAddress;
private String empDesignation,
:
:
//getter + setters
}
I have a returnAllEmployees method in other class
public List<Employees> returnAllEmployees (){
// makes a db call which has lot of joins and returns info for all the employees
}
now my question is I have to filter out the result of returnAllEmployees() based on the search criteria passed i.e. if empName field of searchcriteria is populated as "ABC", the filter list should contain details of all the employees as ABC.
Similarly, if search criteria contains empName="ABC" and empDesignation="engineer", it should filter out the list containing all the employees having name abc and designation as engineer
I know it is possible by using if-else but that would create a lot of lines of codes
Your best solution is to use Java 8 streams. They are perfect for this:
List<Employee> listOfEngineersCalledFred = getAllEmployees().stream()
.filter(emp -> emp.getName().equals("Fred"))
.filter(emp -> emp.getDesignation().equals("Engineer"))
.collect(Collectors.toList());
A technique that I personally find useful and neat is to add static methods that return predicates instead of using getters:
class Employee {
public static Predicate<Employee> hasName(String name) {
return emp -> emp.name.equals(name);
}
}
These can then be used, for example, to find all employees not call Fred:
streamAllEmployees()
.filter(Employee.hasName("Fred").negate())
...
Which seems neater and more deliberate than exposing the field with a getter.
You also might consider converting your getAllEmployees to streamAllEmployees:
public Stream<Employee> streamAllEmployees() {
return employeeList.stream();
}
Then you are telling the user they can do things with the employee objects in the list rather than the list itself.
The nice thing about returning it as a stream is that once you have filtered it you can easily count, group, sort, remove duplicates, get first n etc. You can even trivially convert it to use multiple threads if you are filtering large numbers of items.
For example:
Map<String, Employee> employeesByDesignation = streamAllEmployees()
.collect(Collectors.groupingBy(emp -> emp.getDesignation()));
They are very powerful and worth learning and using.