How to find getter method on basis of JSON Value using Jackson - java

I have json similar to this :
Groups":[
{
"LogicalOperator":"AND",
"condition":[
{
"column":"name",
"Operator":"CONTAINS",
"Value":"Shiva"
},
{
"column":"address",
"Operator":"NOT CONTAINS",
"Value":"Vijay Nagar"
},
{
"column":"city",
"Operator":"EQUAL",
"Value":"Bengaluru"
},
{
"column":"country",
"Operator":"NOT EQUAL",
"Value":"India"
}
]
}
How to find getter method based on column value.
Example: Below column is having "name", "address", "city" and "country".
If the column value is "name" then dynamically I want find getName() method, if the column value is "address" then it should be getAddress()...
Below is the pojo:
public class CustomerPojo {
private String name;
private int age;
private String address;
private String city;
private String country;
public CustomerPojo(String name, String address, String city, String country,int age) {
super();
this.name = name;
this.age=age;
this.address = address;
this.city = city;
this.country = country;
}
#Override
public int hashCode() {
return Objects.hash(address, age, city, country, name);
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CustomerPojo other = (CustomerPojo) obj;
return Objects.equals(address, other.address) && age == other.age && Objects.equals(city, other.city)
&& Objects.equals(country, other.country) && Objects.equals(name, other.name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public String toString() {
return "CustomerPojo [name=" + name + ", age=" + age + ", address=" + address + ", city=" + city + ", country="
+ country + "]";
}
}
Below is the code which I have tried. But I want to do it dynamically.
private List<CustomerPojo> groupOperatorAND(JsonNode condNode, List<CustomerPojo> list) {
// String jsonNode = condNode
// System.out.println(jsonNode);
String column = condNode.findValue("column").asText();
String operator = condNode.findValue("Operator").asText();
String value = condNode.findValue("Value").asText();
switch (operator) {
case "CONTAINS":
if (column.equals("name")) {
containsList = list.stream().filter(li -> li.getName().contains(value)).collect(Collectors.toList());
} else {
containsList = list.stream().filter(li -> li.getAddress().contains(value)).collect(Collectors.toList());
}
// System.out.println(containsList);
// objList.add(containsList);
break;
case "NOT CONTAINS":
if (column.equals("name")) {
notContainsList = containsList.stream().filter(li -> !li.getName().contains(value))
.collect(Collectors.toList());
} else {
notContainsList = containsList.stream().filter(li -> !li.getAddress().contains(value))
.collect(Collectors.toList());
}
// System.out.println(notContainsList);
// objList.add(notContainsList);
break;
case "EQUAL":
if (column.equals("name")) {
equalList = notContainsList.stream().filter(li -> li.getName().equals(value))
.collect(Collectors.toList());
} else {
equalList = notContainsList.stream().filter(li -> li.getAddress().equals(value))
.collect(Collectors.toList());
}
// System.out.println(equalList);
// objList.add(equalList);
break;
case "NOT EQUAL":
if (column.equals("name")) {
notEqualList = equalList.stream().filter(li -> !li.getName().equals(value))
.collect(Collectors.toList());
} else {
notEqualList = equalList.stream().filter(li -> !li.getAddress().equals(value))
.collect(Collectors.toList());
}
//System.out.println("AND Group Result --> " + notEqualList);
// objList.add(notEqualList);
break;
default:
System.out.println("No Operator matches");
}
return notEqualList;
}

If you put this code into a static method or in a constructor so it is only executed once, it will build a map where the key is the "column" name and the value is the associated get method from your CustomerPojo class.
final Map<String, Method> getters = Arrays.asList(CustomerPojo.class.getMethods()).stream()
.filter(mth -> mth.getName().startsWith("get")).filter(mth -> !mth.getName().equals("getClass"))
.collect(Collectors.toMap(
mth -> mth.getName().substring(3, 4).toLowerCase() + mth.getName().substring(4), mth -> mth));
The code streams the array of methods from your CustomerPojo class and filters out all but the "getter" methods.
It then collects the remaining methods into a map where the key is the name of the getter after stripping off "get" and lowercasing the first character.
With this you should be able to:
Method mth = getters.get(columnName);

Related

How to return the string equivalent of an enum value

I'm trying to implement this enum into my program so that it will return the String equivalent of the enum value. So for example, if the value of dept = 3, then it will return Printed Books & eBooks.
This is what I have so far and it doesn't seem to work because when I go to my program tester class and I try to add a new OrderItem it says that the constructor is undefined once I enter an integer from 0-5 for the Department part of the constructor.
Does anyone have any ideas about what I am doing wrong?
The enum
public enum Department {
ELECTRICAL(0), PHOTOGRAPHIC(1), COMPUTING(2), BOOKS(3), MUSIC(4), FASHION(5);
private int dNum;
private static String dept[] = { "Electrical & Electronics", "Cameras & Photography", "Laptops, Desktops & Consoles",
"Printed Books & eBooks", "MP3 & CD Music", "Fashion & Accessories" };
private Department(int num) {
dNum = num;
}
public String toString() {
return dept[dNum];
}
}
The program
public class OrderItem {
private int itemCode;
private String itemName;
private String itemSupplier;
private double itemCost;
private Department dept;
private static int nextCode = 1;
public OrderItem(String itemName, String itemSupplier, double itemCost, Department dept) {
setItemName(itemName);
setItemSupplier(itemSupplier);
setItemCost(itemCost);
setDepartment(dept);
}
public void setItemName(String itemName) {
if (itemName != null) {
this.itemName = itemName;
} else {
if (this.itemName == null)
// a default value
this.itemName = "Unknown";
}
}
public void setItemSupplier(String itemSupplier) {
if (itemSupplier != null) {
this.itemSupplier = itemSupplier;
} else {
if (this.itemSupplier == null)
// a default value
this.itemSupplier = "Unknown";
}
}
public void setItemCost(double itemCost) {
this.itemCost = itemCost;
}
public void setDepartment(Department dept) {
this.dept = dept;
}
public void setDepartment(int dept) {
if (dept == 0)
setDepartment(Department.ELECTRICAL);
else if (dept == 1)
setDepartment(Department.PHOTOGRAPHIC);
else if (dept == 2)
setDepartment(Department.COMPUTING);
else if (dept == 3)
setDepartment(Department.BOOKS);
else if (dept == 4)
setDepartment(Department.MUSIC);
else if (dept == 5)
setDepartment(Department.FASHION);
}
public String getItemName() {
return this.itemName;
}
public String getItemSupplier() {
return this.itemSupplier;
}
public double getItemCost() {
return this.itemCost;
}
public String getDepartment() {
return dept.toString();
}
public int useNextCode() {
itemCode = nextCode;
nextCode++;
return itemCode;
}
public String getDetails() {
String result = "Item name: " + getItemName() + "\n Supplier: " + getItemSupplier() + "\n Department: "
+ getDepartment() + "\n Cost: " + getItemCost();
return result;
}
public String toString() {
System.out.println("Item Code: " + useNextCode());
return getDetails();
}
}
You cannot pass Integer (0-5) in your OrderItem Constructor. Instead you need to pass the desired enum. This should work fine.
OrderItem oi = new OrderItem("PenDrive","HP",300.0, Department.ELECTRICAL);
As the title question was how to return the String value for enum, the answer could be to refactor the enum to have description field instead of inner static array of strings, and add a method to retrieve Department by the ordinal value:
public enum Department {
ELECTRICAL("Electrical & Electronics"),
PHOTOGRAPHIC("Cameras & Photography"),
COMPUTING("Laptops, Desktops & Consoles"),
BOOKS("Printed Books & eBooks"),
MUSIC("MP3 & CD Music"),
FASHION("Fashion & Accessories");
private String description;
private Department(String description) {
this.description = description;
}
public String toString() {
return this.description;
}
public static Department byNum(int ordinal) {
if (ordinal < ELECTRICAL.ordinal() || ordinal > FASHION.ordinal()) {
return null; // or throw IllegalArgumentException
}
return Department.values()[ordinal];
}
}
Then method OrderItem::setDepartment(int dept) may be changed like this (instead of multiple if statements):
public static void setDepartment(int dept) {
Optional.ofNullable(Department.byNum(dept))
.ifPresent(OrderItem::setDepartment);
}

how to add two objects?

I have two classes:-
public class Employee {
private String name;
private String DOB;
private String techicalSkill;
Employee(){
}
Employee(String name, String DOB, String techicalSkill){
this.name=name;
this.DOB=DOB;
this.techicalSkill=techicalSkill;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDOB() {
return DOB;
}
public void setDOB(String dOB) {
DOB = dOB;
}
public String getTechicalSkill() {
return techicalSkill;
}
public void setTechicalSkill(String techicalSkill) {
this.techicalSkill = techicalSkill;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((DOB == null) ? 0 : DOB.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((techicalSkill == null) ? 0 : techicalSkill.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (DOB == null) {
if (other.DOB != null)
return false;
} else if (!DOB.equals(other.DOB))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (techicalSkill == null) {
if (other.techicalSkill != null)
return false;
} else if (!techicalSkill.equals(other.techicalSkill))
return false;
return true;
}
#Override
public String toString() {
return "Employee [name=" + name + ", DOB=" + DOB + ", techicalSkill=" + techicalSkill + "]";
}
}
and
package learning;
public class Person {
private String address;
private int age;
private int weight;
Person(){
}
public Person(String address, int age, int weight) {
super();
this.address = address;
this.age = age;
this.weight = weight;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + age;
result = prime * result + weight;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (age != other.age)
return false;
if (weight != other.weight)
return false;
return true;
}
#Override
public String toString() {
return "Person [address=" + address + ", age=" + age + ", weight=" + weight + "]";
}
}
Now i have created a main class inside which the details are present:-
import java.util.ArrayList;
public class Main {
Employee e1 = new Employee();
Person p1 = new Person();
public static void main(String[] args) {
ArrayList<Employee> arraylist = new ArrayList<>();
arraylist.add(new Employee("Somduti", "31-08-1992", "Java"));
arraylist.add(new Employee("abc", "30-01-1995", "Android"));
arraylist.add(new Employee("xyz", "24-12-1988", "DotNet"));
arraylist.add(new Employee("Sanj", "01-10-1986", "IOS"));
arraylist.add(new Employee("Pink", "19-07-1991", "ETL"));
System.out.println(arraylist);
ArrayList<Person> arraylist1 = new ArrayList<>();
arraylist1.add(new Person("India", 27, 57));
arraylist1.add(new Person("US", 22, 64));
arraylist1.add(new Person("Australia", 31, 69));
arraylist1.add(new Person("France", 33, 77));
arraylist1.add(new Person("Germany", 28, 55));
System.out.println(arraylist1);
}
}
I want to add the two Objects and print the result as below:-
name=Somduti, DOB=31-08-1992, techicalSkill=Java address=India, age=27, weight=57
How do I that?
I think what you want to achieve is a relation between employees and persons. There are various ways to do that. Here are two common solutions:
Association: Add a person-field to the employee class. This looks like: "private Person person;" within the employee class.
Inheritance: An employee is a specific type of person, so you can let employee "extend" the person class. This looks like: public class Employee extends Person ...
Both ways have advantages and disadvantages. For example: Inheritance is a strong relationship, that you might want in this case. Association is a weaker type of relation, so that you could "replace" the person information of an employee (which might not be want you want).
Add the below additional field in the Employee class as follows:
public class Employee {
private String name;
private String DOB;
private String techicalSkill;
private Person person; // Additional field
Employee() {
}
/**
* #param name
* #param dOB
* #param techicalSkill
* #param person
*/
public Employee(final String name, final String dOB, final String techicalSkill, final Person person) {
super();
this.name = name;
this.DOB = dOB;
this.techicalSkill = techicalSkill;
this.person = person; //additional argument in Constructor
}
}
P.S: No changes to the Person class
Test Main:
Person person = new Person("India", 27, 57);
Employee employee = new Employee("Somduti", "31-08-1992", "Java", person);
System.out.println("name= " + employee.getName() + ", DOB= " + employee.getDOB() + ",techicalSkill= " +
employee.getTechicalSkill() + " address= " + employee.getPerson().getAddress() + ", age= " +
employee.getPerson().getAge() + " weight= " + employee.getPerson().getWeight());
Output:
name= Somduti, DOB= 31-08-1992,techicalSkill= Java address= India, age= 27 weight= 57

Get duplicated items with specific format from Java Stream

I'm new with Java streams and I'm playing around with them right now. Given that I receive a list of persons I want to detect which of them are duplicated and print them as "{Id1} is duplicated with {Id3}{Id4} and its duplicated values are Name, Lastname, FamilyName and Birthday"
So this is my person class, I have already override the equals method in order to get the duplicated based on my criterias
public class Person {
private int id;
private String name;
private String familyName;
private String birthday;
private String city;
public Person(int id, String name, String familyName, String birthday, String city) {
this.id = id;
this.name = name;
this.familyName = familyName;
this.birthday = birthday;
this.city = city;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFamilyName() {
return familyName;
}
public void setFamilyName(String familyName) {
this.familyName = familyName;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
#Override
public int hashCode() {
return Objects.hash( name,familyName,birthday,city);
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return false;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Person other = (Person) obj;
if (!Objects.equals(name, other.name)) {
return false;
}
if (!Objects.equals(familyName, other.familyName)) {
return false;
}
if (!Objects.equals(birthday, other.birthday)) {
return false;
}
return true;
}
}
Then, I'm getting the list of duplicates in the following method
personList.stream()
.filter(p -> personList.contains(p))
.collect(Collectors.toList()).forEach(p-> {
System.out.println(p.getId() + " " + p.getName() + " " + p.getFamilyName() + " " + p.getBirthday());
});
It prints the following:
2 Andres Gonzalez 12/4/1990
4 Maureen Perez 15/07/92
7 Andres Gonzalez 12/4/1990
9 Maureen Perez 15/07/92
11 Maureen Perez 15/07/92
As you can see ID's 2 and 7 are duplicated and also 4,9 and 11 are duplicated and those ones are the ones that I need to print in that format but I don't know how to do it with streams so far.
First of all, you should fix your hashCode() implementation to match your equals. If two objects are equal, they must have the same hashCode().
Now, your Stream pipeline returns all elements, since your filter's Predicate will always return true.
Instead, you can group equal elements of the List:
Map<Person,List<Integer>> grouped =
personList.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.mapping(Person::getId,
Collectors.toList())));
Now, for each Person, you have an associated List of identifiers.
You can iterate this Map and print the Persons having Lists with size > 1.
For example:
personList.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.mapping(Person::getId,
Collectors.toList())));
.entrySet()
.stream()
.filter(e -> e.getValue().size() > 1)
.forEach(e -> System.out.println(e.getKey().getId() + " " + e.getKey().getName() + " " + e.getKey().getFamilyName() + " " + e.getKey().getBirthday() + " " + e.getValue()));

How to sort data in repository into alphabetical order using .stream()

I am trying to create a method that sorts and outputs data I have stored in a repository into alphabetical order using .stream(). Currently I have a method that sorts the data by CityID in numeric order which I will add below. Is there a way to adapt it to sort the same data but by CityName in Alphabetical order?
CityID Method -
private void listCityDataInCityIdOrder() {
System.out.format("\033[31m%s\033[0m%n", "City Id Order");
System.out.format("\033[31m%s\033[0m%n", "=============");
repository.getItems()
.stream()
.sorted()
.map(c -> c.toString())
.forEach(str -> System.out.print(str));
}
Data Set -
1,"Cartagena","Spain",3
"2015",0.2,33,26,6,"S"
"2016",0.0,33,24,8,"SSW"
"2017",0.0,32,25,6,"E"
2,"Glasgow","Scotland",3
"2015",0.0,19,8,3,"SE"
"2016",0.1,21,11,6,"SE"
"2017",2.1,19,11,9,"SW"
City Model Class -
package model;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
/**
*
* #author mga
*/
public class City implements Comparable<City>{
private final int id;
private String cityName;
private String country;
private List<YearData> yearDataCollection;
private static int lastIdAllocated = 0;
static final char EOLN='\n';
static final String QUOTE="\"";
public City() {
this.id = ++lastIdAllocated;
this.cityName = "TBC";
this.country = "TBC";
this.yearDataCollection = new ArrayList<>();
}
public City(String cityName, String country) {
this.id = ++lastIdAllocated;
this.cityName = cityName;
this.country = country;
this.yearDataCollection = new ArrayList<>();
}
public City(String cityName, String country, List<YearData> yearDataCollection) {
this.id = ++lastIdAllocated;
this.cityName = cityName;
this.country = country;
this.yearDataCollection = yearDataCollection;
}
public City(int id, String cityName, String country, List<YearData> yearDataCollection) {
this.id = id;
this.cityName = cityName;
this.country = country;
this.yearDataCollection = yearDataCollection;
if (id > City.lastIdAllocated)
City.lastIdAllocated = id;
}
/**
* #return the id
*/
public int getId() {
return id;
}
// Methods required:
public String getCityName() {
return this.cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getCountry() {
return this.country;
}
public void setCountry(String country) {
this.country = country;
}
public List<YearData> getYearDataCollection() {
return this.yearDataCollection;
}
public void setYearDataCollection(List<YearData> yearDataCollection) {
this.yearDataCollection = yearDataCollection;
}
public void addYearData(YearData yearData) {
this.yearDataCollection.add(yearData);
}
#Override
public String toString() {
return "\nCity Id: " + id + " - City Name: " + cityName +
" - Country: " + country + "\nData: " + yearDataCollection + "\n";
}
public String toString(char delimiter) {
final char EOLN='\n';
final String QUOTE="\"";
String str = Integer.toString(this.id) + delimiter +
QUOTE + this.cityName + QUOTE + delimiter +
QUOTE + this.country + QUOTE + delimiter +
Integer.toString(yearDataCollection.size()) + EOLN;
for (YearData yearData : yearDataCollection) {
str += yearData.toString();
}
return str;
}
public boolean equals(Object object) {
if (this == object) return true;
if (!(object instanceof City)) return false;
if (!super.equals(object)) return false;
City city = (City) object;
return getId() == city.getId() &&
java.util.Objects.equals(getCityName(), city.getCityName()) &&
java.util.Objects.equals(getCountry(), city.getCountry()) &&
java.util.Objects.equals(getYearDataCollection(), city.getYearDataCollection());
}
public int hashCode() {
return Objects.hash(super.hashCode(), getId(), getCityName(), getCountry(), getYearDataCollection());
}
#Override
public int compareTo(City compareCity) {
int cityId =
((City) compareCity).getId();
//ascending order
return this.id - cityId;
//descending order
//return cityId - this.id;
}
public static Comparator<City> CityComparator = new Comparator<City>() {
#Override
public int compare(City city1, City city2) {
String cityName1 = city1.getCityName();
String cityName2 = city2.getCityName();
//ascending order
//return cityName1.compareTo(cityName2);
//descending order
return cityName2.compareTo(cityName1);
}
};
}
sure, change your sorted to:
.sorted(Comparator.comparing(City::getCityName))
or using lambda:
.sorted(Comparator.comparing(c -> c.getCityName()))
You can simplify your Comparator
public static Comparator<City> CityComparator = new Comparator<City>() {
#Override
public int compare(City city1, City city2) {
String cityName1 = city1.getCityName();
String cityName2 = city2.getCityName();
//ascending order
//return cityName1.compareTo(cityName2);
//descending order
return cityName2.compareTo(cityName1);
}
};
to just this :
Comparator<City> cityComparatorSimplified = Comparator
.comparing(City::getCityName).reversed(); // reverse for descending order
and then use it further while sorting as
repository.getItems().stream()
.sorted(cityComparatorSimplified)
.map(Object::toString)
.forEach(System.out::print);

Grouping by fields of inner object

I have following two classes:
class Man {
private int id;
private String firstName;
private String lastName;
private int age;
private int countOfChildren;
private Address address;
}
class Address {
private Country country;
private City city;
private String street;
private long quantityOfPeople;
}
I have no idea how to group List<Man> by street and city fields of Address class. How can I do it?
Collectors class provides Collectors.groupingBy(keyProvider, downstream) you can use to group by a pair of values. To pair two values you can either use AbstractMap.SimpleEntry or you can implement your own Pair<T,K> class that represents a pair of two values (it's worth mentioning that you will have to implement hashCode() and equals(object) methods in your Pair class if you want to use it as a key in a hash map). Also two values you want to pair in a key have to implement hashCode() and equals(object) methods - it's worth using immutable classes in this case.
The whole grouping part can be done by:
final Map<Map.Entry<City, String>, List<Man>> groupedByCityAndStreet = people.stream()
.collect(Collectors.groupingBy(
man -> new AbstractMap.SimpleEntry<>(man.getAddress().getCity(), man.getAddress().getStreet()),
Collectors.toList()
));
In this example I have used AbstractMap.SimpleEntry to represent a pair of Country and street. It creates a map where for each key it groups a list of Man object based of country and street. Below you can find a full example:
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
public class GroupByTest {
public static void main(String[] args) {
final List<Man> people = Arrays.asList(
new Man(1, "John", "Doe", 20, 0, new Address(new Country("England"), new City("London"), "Test Street 2", 10000)),
new Man(2, "Mary", "Smith", 54, 4, new Address(new Country("Germany"), new City("Berlin"), "Maine Strasse 32", 10000)),
new Man(3, "James", "Rose", 13, 0, new Address(new Country("England"), new City("London"), "Test Street 2", 10000)),
new Man(4, "Vincent", "Dog", 43, 2, new Address(new Country("Germany"), new City("Berlin"), "Volkswagen Platz 31", 10000)),
new Man(5, "Arnold", "Smoke", 72, 3, new Address(new Country("Italy"), new City("Rome"), "Pepperoni 31", 10000)),
new Man(6, "Katy", "Puppet", 33, 3, new Address(new Country("England"), new City("London"), "Test Street 3", 10000))
);
final Map<Map.Entry<City, String>, List<Man>> groupedByCityAndStreet = people.stream()
.collect(Collectors.groupingBy(
man -> new AbstractMap.SimpleEntry<>(man.getAddress().getCity(), man.getAddress().getStreet()),
Collectors.toList()
));
// Print people associated with given city and street to console
groupedByCityAndStreet.forEach((k, v) -> {
System.out.println("People associated with " + k.getKey().name + ", " + k.getValue() + ":");
v.forEach(man -> {
System.out.println(man);
});
});
}
static final class Man {
private final int id;
private final String firstName;
private final String lastName;
private final int age;
private final int countOfChildren;
private final Address address;
public Man(int id, String firstName, String lastName, int age, int countOfChildren, Address address) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.countOfChildren = countOfChildren;
this.address = address;
}
public int getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public int getCountOfChildren() {
return countOfChildren;
}
public Address getAddress() {
return address;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Man man = (Man) o;
return id == man.id &&
age == man.age &&
countOfChildren == man.countOfChildren &&
Objects.equals(firstName, man.firstName) &&
Objects.equals(lastName, man.lastName) &&
Objects.equals(address, man.address);
}
#Override
public int hashCode() {
return Objects.hash(id, firstName, lastName, age, countOfChildren, address);
}
#Override
public String toString() {
return "Man{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", age=" + age +
", countOfChildren=" + countOfChildren +
", address=" + address +
'}';
}
}
static class Address {
private final Country country;
private final City city;
private final String street;
private final long quantityOfPeople;
public Address(Country country, City city, String street, long quantityOfPeople) {
this.country = country;
this.city = city;
this.street = street;
this.quantityOfPeople = quantityOfPeople;
}
public Country getCountry() {
return country;
}
public City getCity() {
return city;
}
public String getStreet() {
return street;
}
public long getQuantityOfPeople() {
return quantityOfPeople;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Address address = (Address) o;
return quantityOfPeople == address.quantityOfPeople &&
Objects.equals(country, address.country) &&
Objects.equals(city, address.city) &&
Objects.equals(street, address.street);
}
#Override
public int hashCode() {
return Objects.hash(country, city, street, quantityOfPeople);
}
#Override
public String toString() {
return "Address{" +
"country=" + country +
", city=" + city +
", street='" + street + '\'' +
", quantityOfPeople=" + quantityOfPeople +
'}';
}
}
static class City {
private final String name;
public City(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
City city = (City) o;
return Objects.equals(name, city.name);
}
#Override
public int hashCode() {
return Objects.hash(name);
}
#Override
public String toString() {
return "City{" +
"name='" + name + '\'' +
'}';
}
}
static class Country {
private final String name;
public Country(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Country country = (Country) o;
return Objects.equals(name, country.name);
}
#Override
public int hashCode() {
return Objects.hash(name);
}
#Override
public String toString() {
return "Country{" +
"name='" + name + '\'' +
'}';
}
}
}
When you run this example you will something like this in the console:
People associated with Rome, Pepperoni 31:
Man{id=5, firstName='Arnold', lastName='Smoke', age=72, countOfChildren=3, address=Address{country=Country{name='Italy'}, city=City{name='Rome'}, street='Pepperoni 31', quantityOfPeople=10000}}
People associated with London, Test Street 3:
Man{id=6, firstName='Katy', lastName='Puppet', age=33, countOfChildren=3, address=Address{country=Country{name='England'}, city=City{name='London'}, street='Test Street 3', quantityOfPeople=10000}}
People associated with Berlin, Volkswagen Platz 31:
Man{id=4, firstName='Vincent', lastName='Dog', age=43, countOfChildren=2, address=Address{country=Country{name='Germany'}, city=City{name='Berlin'}, street='Volkswagen Platz 31', quantityOfPeople=10000}}
People associated with Berlin, Maine Strasse 32:
Man{id=2, firstName='Mary', lastName='Smith', age=54, countOfChildren=4, address=Address{country=Country{name='Germany'}, city=City{name='Berlin'}, street='Maine Strasse 32', quantityOfPeople=10000}}
People associated with London, Test Street 2:
Man{id=1, firstName='John', lastName='Doe', age=20, countOfChildren=0, address=Address{country=Country{name='England'}, city=City{name='London'}, street='Test Street 2', quantityOfPeople=10000}}
Man{id=3, firstName='James', lastName='Rose', age=13, countOfChildren=0, address=Address{country=Country{name='England'}, city=City{name='London'}, street='Test Street 2', quantityOfPeople=10000}}
Hope it helps.

Categories