Equalization Two Lists in java - java

i have two lists (personList From DB and inputPersonList from UI).
I want to make sure each row in personList find (matches) corresponding row in inputPersonList according to id(without sort)
Person person1=new Person();
Person person2=new Person();
Person person1=new Person();
List<Person> personList=new ArrayList();
List<Person> inputPersonList=new ArrayList();
person1.Id(1);
person1.setName("A");
person1.setFamily("B");
person2.Id(2);
person2.setName("C");
person2.setFamily("D");
person3.Id(3);
person3.setName("E");
person3.setFamily("F");
personList.add(person1);
personList.add(person2);
personList.add(person3);
inputPersonList.add(person1);
inputPersonList.add(person3);
inputPersonList.add(person2);

Assuming your list contains a custom Object. If so just overwrite the compareTo method in your custom Object and then iterate through the List, checking each corresponding element.
For example:
Here is a custom Book object that implements Comparable:
public class Book implements Comparable {
String isbn;
String title;
public Book(String id, String title) {
this.isbn = id;
this.title = title;
}
String getIsbn() {
return isbn;
}
String getTitle() {
return title;
}
#Override
public int compareTo(Object o) {
return Comparator
.comparing(Book::getIsbn)
.thenComparing(Book::getTitle)
.compare(this, (Book) o);
}
#Override
public String toString() {
String output = new StringBuilder()
.append(isbn).append(":").append(title)
.toString();
return output;
}
}
The following creates two lists (to represent the DB list and the UI lists) and then compares them based on position in the list (namely "corresponding row"):
public void CompareTwoLists(){
List<Book> libraryUI = new ArrayList<>();
libraryUI.add(new Book("9780593098240", "Children of Dune"));
libraryUI.add(new Book("9780593098233", "Dune Messiah"));
libraryUI.add(new Book("9780441172719", "Dune"));
List<Book> libraryDB = new ArrayList<>();
libraryDB.add(new Book("9780593098240", "Children of Dune"));
libraryDB.add(new Book("9780593098233", "Dune Messiah"));
libraryDB.add(new Book("9788886845687", "God Emperor of Dune"));
boolean theSame = Boolean.TRUE;
if(libraryDB.size() != libraryUI.size()) {
theSame = Boolean.FALSE;
} else {
for(int i = 0; i < libraryDB.size(); i++) {
if (libraryDB.get(i).compareTo(libraryUI.get(i)) != 0) {
theSame = Boolean.FALSE;
break;
}
}
}
if(theSame) {
System.out.println("The same");
} else {
System.out.println("Not the same");
}
}

What you can do is check if each of the two lists contains all the elements of the other list and their size is equal:
public static void main(String[] args) throws ParseException {
Person person1 = new Person();
Person person2 = new Person();
Person person3 = new Person();
List<Person> personList = new ArrayList<>();
List<Person> inputPersonList = new ArrayList<>();
person1.Id(1);
person1.setName("A");
person1.setFamily("B");
person2.Id(2);
person2.setName("C");
person2.setFamily("D");
person3.Id(3);
person3.setName("E");
person3.setFamily("F");
personList.add(person1);
personList.add(person2);
personList.add(person3);
inputPersonList.add(person1);
inputPersonList.add(person3);
inputPersonList.add(person2);
// compare the lists using the built-in "equals()" method, which considers order of elements
System.out.println(personList.equals(inputPersonList) ?
"equal (considering order)" : "not equal (considering order)");
// then compare them with the other possibility
System.out.println(areEqual(personList, inputPersonList) ?
"equal (without considering order)" : "not equal (without considering order)");
}
public static boolean areEqual(List<Person> persons, List<Person> personsToo) {
if (persons.containsAll(personsToo) && personsToo.containsAll(persons)
&& persons.size() == personsToo.size()) {
return true;
} else {
return false;
}
}
Keep in mind that this does not consider the case of duplicate elements correctly, because it only checks if an element is present in both lists, not if their count in the lists is equal. You could add person1 a second time to personList and person3 a second time to imputPersonList and the result would still be true respectively equality.

As says Ambro-r you need use the Comparable interface but if you don't have access to the Entity, you should extends Book Class.
public class MyBook extends Book implements Comparable {
#Override
public int compareTo(Object o) {
//compare with other book with the attributes what you want maybe could:
return this.isbn > ((MyBook) o).isbn
}
#Override
public String toString() {
//return super.toString() or your own toString
}
Then you should create lists of MyBook objects.

Related

Joining 2 Arraylists JAVA

So I have this class which reads from 2 files and fills 2 Arraylists
with Contact Objects. Now I want to Merge these Arraylists to a new
Arraylist which then I want to Sort and eliminate duplicates. My
problem is: How do I get the filled Arraylists to another method so I
can do the sorting?
Here is my Code:
import java.util.List;
import java.util.Scanner;
final class Addressbook{
public List<Contact> contacts1 = new ArrayList<Contact>();
public List<Contact> contacts2= new ArrayList<Contact>();
public List<Contact> allcontacts = new ArrayList<Contact>();
public void readContacts1(Scanner scanner1) {
scanner1.useDelimiter(";");
while (scanner1.hasNext()) {
final Contact contact= readContacts1(scanner1);
contacts1.add(Contact);
}
}
public void readContacts2(Scanner scanner2) {
while (scanner2.hasNext()) {
final Contact contact = readContacts2(scanner2);
contacts.add(contact);
}
}
public int ContactSearch1(Contact c) {
for (int i = 0; i < contacts1.size(); i++)
if (contacts1.get(i).equals(c))
return i;
return -1;
}
public int ContactSearch2(Contact c) {
for (int i = 0; i < contacts2.size(); i++)
if (contacts2.get(i).equals(c))
return i;
return -1;
}
private static Contact readContact1(Scanner scanner1) {
scanner1.useDelimiter(";");
final String name= scanner1.next();
final String lastname = scanner1.next();
final String address = scanner1.next();
final String number = scanner1.next();
final Contact contact= new Contact(name, lastname, address, number);
return contact;
}
private static Contact ReadContact2(Scanner scanner2) {
scanner2.useDelimiter(";");
final String name= scanner2.next();
final String lastname = scanner2.next();
final String address = scanner2.next();
final String number = scanner2.next();
final Contact contact= new Contact(name, lastname, address, number);
return contact;
}
}
First, the provided code contains a lot of duplicated parts which may easily be encapsulated in a separate helper class which takes care of reading and searching the lists.
final class Addressbook{
private List<Contact> contacts1;
private List<Contact> contacts2;
private List<Contact> allContacts;
private static class ContactHelper {
public static List<Contact> readContacts(Scanner scanner) {
// scanner.setDelimiter(";"); // it's better to set this parameter in the call
List<Contact> result = new ArrayList<>();
boolean hasData = scanner.hasNext();
while (hasData) {
final String name= scanner.next();
final String lastname = (hasData &= scanner.hasNext()) ? scanner.next() : "NO_LAST_NAME";
final String address = (hasData &= scanner.hasNext()) ? scanner.next() : "NO_ADDRESS";
final String number = (hasData &= scanner.hasNext()) ? scanner.next() : "NO_NUMBER";
result.add(new Contact(name, lastname, address, number));
hasData = scanner.hasNext();
}
return result;
}
public static int indexOfContact(Contact contact, List<Contact> list) {
Objects.requireNonNull(contact);
Objects.requireNonNull(list);
for (int i = 0, n = list.size(); i < n; i++) {
if (contact.equals(list.get(i))) {
return i;
}
}
return -1;
}
}
}
Then appropriate methods to set fields contacts1, contacts2 should use the helper's methods:
// class AddressBook
public void readContacts1(Scanner scanner) {
contacts1 = ContactHelper.readContacts(scanner);
}
public void readContacts2(Scanner scanner) {
contacts2 = ContactHelper.readContacts(scanner);
}
A method to join the lists, sort them, and remove the duplicates can be implemented using TreeSet if class Contact implements interface Comparable required for sorting the contacts in their natural order, otherwise custom comparator must be provided.
// another helper method
public static List<Contact> joinContacts(List<Contact> ... contactLists) {
Set<Contact> sortedWithoutDups = new TreeSet<>();
for (List<Contact> list : contactLists) {
if (null != list) {
sortedWithoutDups.addAll(list);
}
}
return new ArrayList<>(sortedWithoutDups);
}
// setting allContacts
public void joinContacts() {
allContacts = AddressBook.joinContacts(contacts1, contacts2);
}
This task can be resolved using Stream API (allowing for joining more than 2 lists any of which may be null):
// AddressBook
public void joinContacts() {
allContacts = ContactHelper.joinContactLists(contacts1, contacts2);
}
// ContactHelper
public static List<Contact> joinContactLists(List<Contact> ... lists) {
return Arrays.stream(lists) // Stream<List<Contact>>
.filter(Objects::nonNull) // filter out null lists
.flatMap(List::stream) // convert to Stream<Contact>
.sorted() // sort
.distinct() // _and then_ remove duplicates
.collect(Collectors.toList());
}
contacts1.addAll(contacts2);
contacts1.sort((o1, o2) -> o1 < o2 ? o1 : o2);
contacts1.addAll(contacts2)
This adds all contacts2 to contacts1 and contacts1 List will have all the contacts.
Here u can replace o1 < o2 can be replaced with the logic u need to sort.
The easiest way to ensure, that you do not have duplicates in your ArrayList is to copy your list into a Collection that does not allow duplicates (for example a set) and then copy it back into the ArrayList you need. I would recommend to check out this post for this:
Answers to Question: I have an ArrayList, and I want to remove repeated strings from it. How can I do this?
Ultimately your problem could be answered the following way (using the code of mentioned blog post):
allcontacts.addAll(contacts1);
allcontacts.addAll(contacts2);
Set<Contact> set = new HashSet<>(allcontacts);
allcontacts.clear();
allcontacts.addAll(set);
Now you got rid of all duplicates and merged the ArrayLists contacts1 and contacts2 into allcontacts.
You now only have to sort allcontacts, which can be done like this (if Contact implements Comparable):
Collections.sort(allcontacts);

How to sort an ArrayList of type Student? [duplicate]

I have simple class
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
and List<ActiveAlarm> con. How to sort in ascending order by timeStarted, then by timeEnded? Can anybody help? I know in C++ with generic algorithm and overload operator <, but I am new to Java.
Using Comparator
For Example:
class Score {
private String name;
private List<Integer> scores;
// +accessor methods
}
Collections.sort(scores, new Comparator<Score>() {
public int compare(Score o1, Score o2) {
// compare two instance of `Score` and return `int` as result.
return o2.getScores().get(0).compareTo(o1.getScores().get(0));
}
});
With Java 8 onwards, you can simply use lambda expression to represent Comparator instance.
Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });
Either make ActiveAlarm implement Comparable<ActiveAlarm> or implement Comparator<ActiveAlarm> in a separate class. Then call:
Collections.sort(list);
or
Collections.sort(list, comparator);
In general, it's a good idea to implement Comparable<T> if there's a single "natural" sort order... otherwise (if you happen to want to sort in a particular order, but might equally easily want a different one) it's better to implement Comparator<T>. This particular situation could go either way, to be honest... but I'd probably stick with the more flexible Comparator<T> option.
EDIT: Sample implementation:
public class AlarmByTimesComparer implements Comparator<ActiveAlarm> {
#Override
public int compare(ActiveAlarm x, ActiveAlarm y) {
// TODO: Handle null x or y values
int startComparison = compare(x.timeStarted, y.timeStarted);
return startComparison != 0 ? startComparison
: compare(x.timeEnded, y.timeEnded);
}
// I don't know why this isn't in Long...
private static int compare(long a, long b) {
return a < b ? -1
: a > b ? 1
: 0;
}
}
JAVA 8 and Above Answer (Using Lambda Expressions)
In Java 8, Lambda expressions were introduced to make this even easier! Instead of creating a Comparator() object with all of it's scaffolding, you can simplify it as follows: (Using your object as an example)
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted);
or even shorter:
Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod));
That one statement is equivalent to the following:
Collections.sort(list, new Comparator<ActiveAlarm>() {
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return a1.timeStarted - a2.timeStarted;
}
});
Think of Lambda expressions as only requiring you to put in the relevant parts of the code: the method signature and what gets returned.
Another part of your question was how to compare against multiple fields. To do that with Lambda expressions, you can use the .thenComparing() function to effectively combine two comparisons into one:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted
.thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);
The above code will sort the list first by timeStarted, and then by timeEnded (for those records that have the same timeStarted).
One last note: It is easy to compare 'long' or 'int' primitives, you can just subtract one from the other. If you are comparing objects ('Long' or 'String'), I suggest you use their built-in comparison. Example:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );
EDIT: Thanks to Lukas Eder for pointing me to .thenComparing() function.
We can sort the list in one of two ways:
1. Using Comparator : When required to use the sort logic in multiple places
If you want to use the sorting logic in a single place, then you can write an anonymous inner class as follows, or else extract the comparator and use it in multiple places
Collections.sort(arrayList, new Comparator<ActiveAlarm>() {
public int compare(ActiveAlarm o1, ActiveAlarm o2) {
//Sorts by 'TimeStarted' property
return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2);
}
//If 'TimeStarted' property is equal sorts by 'TimeEnded' property
public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) {
return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0;
}
});
We can have null check for the properties, if we could have used 'Long' instead of 'long'.
2. Using Comparable(natural ordering): If sort algorithm always stick to one property:
write a class that implements 'Comparable' and override 'compareTo' method as defined below
class ActiveAlarm implements Comparable<ActiveAlarm>{
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(long timeStarted,long timeEnded) {
this.timeStarted=timeStarted;
this.timeEnded=timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
public int compareTo(ActiveAlarm o) {
return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o);
}
public int doSecodaryOrderSort(ActiveAlarm o) {
return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0;
}
}
call sort method to sort based on natural ordering
Collections.sort(list);
In java8+ this can be written in single line as follows:
collectionObjec.sort(comparator_lamda) or comparator.comparing(CollectionType::getterOfProperty)
code:
ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
or
ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))
public class ActiveAlarm implements Comparable<ActiveAlarm> {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public int compareTo(ActiveAlarm a) {
if ( this.timeStarted > a.timeStarted )
return 1;
else if ( this.timeStarted < a.timeStarted )
return -1;
else {
if ( this.timeEnded > a.timeEnded )
return 1;
else
return -1;
}
}
That should give you a rough idea. Once that's done, you can call Collections.sort() on the list.
Since Java8 this can be done even cleaner using a combination of Comparator and Lambda expressions
For Example:
class Student{
private String name;
private List<Score> scores;
// +accessor methods
}
class Score {
private int grade;
// +accessor methods
}
Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade);
Java-8 solution using Stream API:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded))
.collect(Collectors.toList());
B. When timeStarted and timeEnded have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded))
.collect(Collectors.toList());
If you want to sort the original list itself:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
list.sort(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded));
B. When timeStarted and timeEnded have public getter methods:
list.sort(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded));
Guava's ComparisonChain:
Collections.sort(list, new Comparator<ActiveAlarm>(){
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return ComparisonChain.start()
.compare(a1.timestarted, a2.timestarted)
//...
.compare(a1.timeEnded, a1.timeEnded).result();
}});
We can use the Comparator.comparing() method to sort a list based on an object's property.
class SortTest{
public static void main(String[] args) {
ArrayList<ActiveAlarm> activeAlarms = new ArrayList<>(){{
add(new ActiveAlarm("Alarm 1", 5, 10));
add(new ActiveAlarm("Alarm 2", 2, 12));
add(new ActiveAlarm("Alarm 3", 0, 8));
}};
/* I sort the arraylist here using the getter methods */
activeAlarms.sort(Comparator.comparing(ActiveAlarm::getTimeStarted)
.thenComparing(ActiveAlarm::getTimeEnded));
System.out.println(activeAlarms);
}
}
Note that before doing it, you'll have to define at least the getter methods of the properties you want to base your sort on.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(String name, long timeStarted, long timeEnded) {
this.name = name;
this.timeStarted = timeStarted;
this.timeEnded = timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
#Override
public String toString() {
return name;
}
}
Output:
[Alarm 3, Alarm 2, Alarm 1]
Employee POJO Class
package in.ac.adit.oop.sort;
public class Employee {
private int id;
private String name;
private String department;
public int getId() {
return id;
}
public Employee() {
super();
}
public Employee(int id, String name, String department) {
super();
this.id = id;
this.name = name;
this.department = department;
}
#Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]";
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
Employee Class To Manage Employee
package in.ac.adit.oop.sort;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
/*
* Create 10 Employee Object
*/
Employee emp1 = new Employee(1, "Nayan", "IT");
Employee emp2 = new Employee(2, "Siddarth", "CP");
Employee emp3 = new Employee(3, "Samarth", "AE");
Employee emp4 = new Employee(4, "Bhavesh", "CV");
Employee emp5 = new Employee(5, "Sam", "FT");
Employee emp6 = new Employee(6, "Keyur", "IT");
Employee emp7 = new Employee(7, "Bala", "ME");
Employee emp8 = new Employee(8, "Mitul", "ME");
Employee emp9 = new Employee(9, "Kamlesh", "EE");
Employee emp10 = new Employee(10, "Piyush", "EE");
/*
* List of Employee Object
*/
List<Employee> employeeList = new ArrayList<Employee>();
employeeList.add(emp1);
employeeList.add(emp2);
employeeList.add(emp3);
employeeList.add(emp4);
employeeList.add(emp5);
employeeList.add(emp6);
employeeList.add(emp7);
employeeList.add(emp8);
employeeList.add(emp9);
employeeList.add(emp10);
CustomObjectSort customObjectSort = new CustomObjectSort();
List<Employee> sortByDepartment = customObjectSort.sortByDepartment(employeeList);
/*
* Sorted By Department
*/
for (Employee employee : sortByDepartment) {
System.out.println(employee);
}
/*
* Sorted By Name
*/
List<Employee> sortByName = customObjectSort.sortByName(employeeList);
for (Employee employee : sortByName) {
System.out.println(employee);
}
/*
* Sorted By Id
*/
List<Employee> sortById = customObjectSort.sortById(employeeList);
for (Employee employee : sortById) {
System.out.println(employee);
}
}
}
Custom Sorting
package in.ac.adit.oop.sort;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CustomObjectSort {
public List<Employee> sortByName(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getName().compareTo(employee2.getName());
}
});
return employeeList;
}
public List<Employee> sortByDepartment(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getDepartment().compareTo(employee2.getDepartment());
}
});
return employeeList;
}
public List<Employee> sortById(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getId() - employee2.getId();
}
});
return employeeList;
}
}
You can use Collections.sort and pass your own Comparator<ActiveAlarm>
In java you need to use the static Collections.sort method. Here is an example for a list of CompanyRole objects, sorted first by begin and then by end. You can easily adapt for your own object.
private static void order(List<TextComponent> roles) {
Collections.sort(roles, new Comparator() {
#Override
public int compare(Object o1, Object o2) {
int x1 = ((CompanyRole) o1).getBegin();
int x2 = ((CompanyRole) o2).getBegin();
if (x1 != x2) {
return x1 - x2;
} else {
int y1 = ((CompanyRole) o1).getEnd();
int y2 = ((CompanyRole) o2).getEnd();
return y2 - y1;
}
}
});
}
You can call Collections.sort() and pass in a Comparator which you need to write to compare different properties of the object.
As mentioned you can sort by:
Making your object implement Comparable
Or pass a Comparator to Collections.sort
If you do both, the Comparable will be ignored and Comparator will be used. This helps that the value objects has their own logical Comparable which is most reasonable sort for your value object, while each individual use case has its own implementation.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
List<ActiveAlarm> con = new ArrayList<ActiveAlarm>();
Collections.sort(con , (a1, a2) -> a1.timeStarted.compareTo(a2.timeStarted));
Collections.sort(con , (a1, a2) -> a1.timeEnded.compareTo(a2.timeEnded));
Here's what did the trick for me.
Was much shorter and easier than everything else I found:
Collections.sort(listName, Comparator.comparing(Object::getProperty).reversed());
The ".reversed()" part at the end was a requirement for my specific project but I'm sharing it too, as it took a while to find it
The best and the easiest way to sort any list of objects in Java (Java 8 and above).
Lets sort a basket of fruits based on the property "fruitName"
Fruit POJO:
class Fruit
{
int price;
String fruitName;
public Fruit(int price, String fruitName) {
super();
this.price = price;
this.fruitName = fruitName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getFruitName() {
return fruitName;
}
public void setFruitName(String fruitName) {
this.fruitName = fruitName;
}
#Override
public String toString() {
return "Fruits [price=" + price + ", fruitName=" + fruitName + "]";
}
}
Now lets add fruits into a list and then sort it
List<Fruit> basketOfFruits = new ArrayList<>();
basketOfFruits.add(new Fruit(123, "oranges"));
basketOfFruits.add(new Fruit(45, "nectarine"));
basketOfFruits.add(new Fruit(369, "blueberries"));
basketOfFruits.add(new Fruit(248, "apple"));
basketOfFruits.add(new Fruit(968, "peaches"));
basketOfFruits.add(new Fruit(436, "grapes"));
basketOfFruits.add(new Fruit(596, "figs"));
//sorting by the property fruitName
Collections.sort(basketOfFruits, (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());});
You can now print the list (i.e basketOfFruits) and the fruits in the list would be sorted in ASCENDING order (lexicographically).
The output would look like this:
[Fruits [price=248, fruitName=apple], Fruits [price=369, fruitName=blueberries], Fruits [price=596, fruitName=figs], Fruits [price=436, fruitName=grapes], Fruits [price=45, fruitName=nectarine], Fruits [price=123, fruitName=oranges], Fruits [price=968, fruitName=peaches]]
Instead of Collections.sort(), Java streams can also be used (Java 8 and above). The following is the code using Java streams
List<Fruit> sortedFruits = basketOfFruits.stream().sorted( (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());}).collect(Collectors.toList());
here the list is sorted in the same manner as Collections.sort(), but the sorted items would be stored/collected in another list "sortedFruits". So, if we want to print the sorted items of the list, we need to print "sortedFruits" instead of "basketOfFruits" in this case

add and share arraylist

I'm trying to create a Person class which has getName() method, addFriend(Person R) method, ArrayList<Person> getFriendList()
String Name;
private ArrayList Person friend = new ArrayList Person ();
public Person(String name)
{
this.Name=name;
}
public ArrayList<Person> getFriendList(){
return friend;
}
public void addFriend(Person R){
friend.add(R);
}
FriendsOfFriends(){
//list of friends of friends of this person.
}
public static int (p,q){
//return the number of friends shared by both R and q.
}
public static int numberOfMutualFriends(Person p, Person q){
//return the number of friends shared by both R and q.
return intersection(p.friend,q.friend).size();
}
public List<Person> intersection(List<Person> list1, List<Person> list2) {
List<Person> list = new ArrayList<Person>();
for (Person t : list1) {
if(list2.contains(t)) {
list.add(t);
}
}
return list;
}
You'll need to redefine the hashCode and the equals method in order to make it work.
Seems you're studying bulk operations on collections.
To get friends of friends, use Set#addAll() in the for-each loop:
List<Person> getFriendsOfFriends() {
Set<Person> res = new HashSet<>(); // empty set
for (Person p : this.friends)
res.addAll(p.friends); // add all p's friends
return new ArrayList<>(res); // copy to ArrayList and return
}
To get number of mutual friends, use Set#retainAll():
public static int numberOfMutualFriends(Person p, Person q) {
// set containing friends of p (not to modify p.friends itself)
Set<Person> res = new HashSet<>(p.friends);
res.retainAll(q.friends); // leave only mutual friends
return res.size();
}
This will work if there are no Person clones in data (i. e. every Person is presented as exactly one object). Otherwise, to make it work correctly, you must override .equals() and .hashCode() in Person class.

How to compare two array lists for similar objects which differ in at least one property in java?

I have two array list. Each has list of Objects of type User.
The User class looks like below
public class User {
private long id;
private String empCode;
private String firstname;
private String lastname;
private String email;
public User( String firstname, String lastname, String empCode, String email) {
super();
this.empCode = empCode;
this.firstname = firstname;
this.lastname = lastname;
this.email = email;
}
// getters and setters
}
import java.util.ArrayList;
import java.util.List;
public class FindSimilarUsersWithAtLeastOneDifferentProperty {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List<User> list1 = new ArrayList<User>();
list1.add(new User("F11", "L1", "EMP01", "u1#test.com"));
list1.add(new User("F2", "L2", "EMP02", "u222#test.com"));
list1.add(new User("F3", "L3", "EMP03", "u3#test.com"));
list1.add(new User("F4", "L4", "EMP04", "u4#test.com"));
list1.add(new User("F5", "L5", "EMP05", "u5#test.com"));
list1.add(new User("F9", "L9", "EMP09", "u9#test.com"));
list1.add(new User("F10", "L10", "EMP10", "u10#test.com"));
List<User> list2 = new ArrayList<User>();
list2.add(new User("F1", "L1", "EMP01", "u1#test.com"));
list2.add(new User("F2", "L2", "EMP02", "u2#test.com"));
list2.add(new User("F6", "L6", "EMP06", "u6#test.com"));
list2.add(new User("F7", "L7", "EMP07", "u7#test.com"));
list2.add(new User("F8", "L8", "EMP08", "u8#test.com"));
list2.add(new User("F9", "L9", "EMP09", "u9#test.com"));
list2.add(new User("F100", "L100", "EMP10", "u100#test.com"));
List<User> resultList = new ArrayList<User>();
// this list should contain following users
// EMP01 (common in both list but differs in firstname)
// EMP02 (common in both list but differs in email)
// EMP10 (common in both list but differs in firstname, lastname and email)
}
}
If you see the sample code, the two lists have four users with emp code EMP01, EMP02, EMP09 and EMP10 common.
So, we only need to compare the properties of these four users.
If any of the users have at least one different property it should be added in the result list.
Please advise on how do I go about this?
Implement equals, hashcode in User
#Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!(obj instanceof User))
return false;
User u = (User) obj;
return this.empCode == null ? false : this.empCode
.equals(u.empCode);
}
#Override
public int hashCode() {
return this.empCode == null ? 0 : this.empCode.hashCode();
}
#Override
public String toString() {
return "Emp Code: " + this.empCode;
}
Then use retainAll
list2.retainAll(list1);-->EMP01, EMP02, EMP09, EMP10
I think this what you should do -
for(User user1 : list1) {
for(User user2 : list2) {
if(user1.getEmpCode().equals(user2.getEmpCode())) {
if(!user1.getFirstName().equals(user2.getFirstName()) ||
!user1.getLastName().equals(user2.getLastName()) ||
!user1.getEmail().equals(user2.getEmail())) {
resultList.add(user1);
}
}
}
}
It might not make sense for the User to override equal and hashCode only to serve this purpose. They should be overriden in the way in which it makes more sense domain-wise.
This is simple. Override equal method in your User class. One very simple implementation(you can enhance it by using null checks etc) can be like below:
#override
public boolean equals(Object obj) {
User other = (User) obj;
if(this.id==other.id
&& this.empCode.equals(other.empCode)
&& this.firstname.equals(other.firstname)
&& this.lastname.equals(other.lastname)
&& this.email.equals(other.email)){
return true;
}else{
return false;
}
}
Once done, you can use:
for(user user: list1){
if(!resultList.contains(user)){
resultList.add(user);
}
}
for(user user: list2){
if(!resultList.contains(user)){
resultList.add(user);
}
}
The canonical approach is as follows:
Write a method countDifferences that counts the number of differences between users
For each object in one list, find the minimum when compared to the other lists objects
Report all objects where the minimum is not 0.
If you put weights on the different properties you can also control that e.g. a match in the ID attribute is stronger than a match in the name.
Update: sorry, misread your comment that the ID attribute must match.
Replace 2) with "find object which has the same ID". Other than that, I still recommend counting the number of differences. It is more flexible, as you can define thresholds for good or bad matches etc.
Add this method to your User class:
public boolean isSimilarButNotEqual(User other) {
if(!this.empCode.equals(other.empCode))
return false;
return !(this.firstname + this.lastname + this.email).equals(other.firstname + other.lastname + other.email);
}
Then, in the main() do:
for(User user1: list1){
for(User user2: list2){
if(user1.isSimilarButNotEqual(user2)){
resultList.add(user1);
resultList.add(user2);
}
}
}
I have used the following way to compare two custom ArrayList.
List<SinglePostData> allPosts = new ArrayList<>();
List<SinglePostData> noRepeatAllPosts = new ArrayList<>();
for (int i = 0; i < allPosts.size(); i++) {
boolean isFound = false;
for (int j = i+1; j < allPosts.size(); j++) {
if (allPosts.get(i).getTitle().equals(allPosts.get(j).getTitle())) {
isFound = true;
break;
}
}
if (!isFound) noRepeatAllPosts.add(allPosts.get(i));
}

How can I order TreeMaps or ArrayLists holding Persons based on their ID, name, or birthdate?

I have tried almost everything and I can't seem to get my lists to order themselves.
Here's some code:
private List<Person> names = new ArrayList<Person>();
private Map<Integer, Person> peopleMap = new TreeMap <Integer, Person>();
for(int i = 0; i<20; i++)
{
Person personOne = new Person();
peopleMap.put(personOne.id,personOne);
names.add(personOne);
}
Collections.sort(names);
run();
}
My Person class:
public class Person implements Comparable {
public String name;
public int id;
public Date birthdate;
static int idRecord = 0;
The values are filled with randoms. My date has a date format.
I also have a toString method inside my person class, but for some reason when I try to print my maps it gives me the hashcode (this is the hashcode right?) Person#a62fc3.
Here is my toString inside the person clasS:
public String toString()
{
char tab = '\t';
return ("ID Number: "+id+tab+" Name: "+tab+name+tab+" Birthdate: "+(birthdate.toString()));
}
I should add that I am not able to call my toString method inside my person class. Because it is printing Person#a62fc3.
public void sortByID()
{
char tab = '\t';
for (int i = 1; i<20; i++)
System.out.println((peopleMap.get(i)).toString());
//System.out.println("ID Number: "+(peopleMap.get(i).id)+tab+" Name: "+tab+peopleMap.get(i).name+tab+" Birthdate: "+peopleMap.get(i).birthdate);
run();
}
The commented code will work but the code calling the toString does not print what it should
Compare to method inside of my Person class:
public int compareTo(Object obj) {
Person o = (Person) obj;
if (this.id == o.id) { return 0; }
if (this.id > o.id) { return 1; }
if (this.id < o.id) { return -1; }
return 0;
I can provide more code if it's needed.
Compare by name method and it's output. Should I make an arrayList to store my values in and then sort it in that?
public void sortByName()
{
// char tab = '\t';
for(int j = 1; j<20; j++)
{
// System.out.println("ID Number: "+(names.get(j).id)+tab+" Name: "+tab+peopleMap.get(j).name+tab+" Birthdate: "+peopleMap.get(i).birthdate);
//Person p = names.get(j);
System.out.println(names.get(j).toString());
}
}
Output:
Person#10b30a7
Person#1a758cb
Person#1b67f74
Person#69b332
Person#173a10f
Person#530daa
Person#a62fc3
Person#89ae9e
Person#1270b73
Person#60aeb0
Person#16caf43
Person#66848c
Person#8813f2
Person#1d58aae
Person#83cc67
Person#e09713
Person#de6f34
Person#156ee8e
Person#47b480
Thanks
Well, I can't pinpoint the exact problem, I have a few suggestions.
Maps aren't sorted.
In general, an Map is not sorted, so you will not be able to sort the keys of the map. If you want to sort the Map use the SortedMap interface.
Use Generics when possible
The Comparable interface is generic. You should probably be implementing Comparable<Person>
Then your compareTo() method should look like this:
public int compareTo(Person p) {
if (this.id > p.id) return 1;
else if (this.id < p.id) return -1;
else return 0;
}
The difference between Comparator<Person> and Comparable<Person>
You need to take a look at the Comparator interface as well as the Comparable interface.
Your Person should implement comparable in that way that you usually want a person to be sorted. Then you should write some implementations of Comparator.
public classPersonNameComparator implements Comparator<Person> {
public int compare(Person p1, Person p2) {
return p1.name.compareTo(p2.name);
}
}
The importance of using the #Override annotation
It is important to always use the #Override annotation whenever you are trying to override a method of a super class or implement an interface method. The following are a few links regarding why this is a good idea:
Overriding the java equals() method quirk
When do you use Java's #Override annotation and why?
One issue that I see is that TreeMap sorts by key not by value. Your compareTo will not be used in the sorting of the tree since it is the value in the map. Since the key in the map is the id the the items in the tree should be sorted by the id of the person.
How do you know that the map isn't sorted? Can you show us some output that shows that it is not? Are you by any chance changing the ID of the Person after it gets put into the map?
Oh, and what is names compared to personMap? Also, are the ids really contiguous starting from 1? What does this code spit out:
for (Person person : peopleMap.values()) {
System.out.println(person);
}
did you use the #Override method to make sure that you are actually overriding the toString method? It looks like it is still printing out the default toString() (ie the value of the pointer to the object).
see : comparator API.
"The ordering imposed by a Comparator c on a set of elements S is said to be consistent with equals if and only if (compare((Object)e1, (Object)e2)==0) has the same boolean value as e1.equals((Object)e2) for every e1 and e2 in S."
I don't see an equals method in your Person class. The default implementation of equals compares identity. And if you override equals, you must define hashCode two.
And this question : Consistent Equals() results, but inconsistent TreeMap.containsKey() result
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class Person implements Comparable<Person> {
public final String name;
public final int id;
public final Date birthdate;
public Person(int id, String name, Date birthdate) {
this.id = id;
this.name = name;
this.birthdate = birthdate;
}
public static void main(String[] args) {
List<Person> list = new ArrayList<Person>();
for (int i = 10; i > 0; i--) {
list.add(new Person(i, "name" + String.valueOf(i), new Date()));
}
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
#Override
public boolean equals(Object other) {
if (!(other instanceof Person)) {
return false;
}
return this.id == ((Person)other).id;
}
#Override
public int hashCode() {
return 41 * id;
}
#Override
public String toString() {
return "Person<" + id + ">";
}
#Override
public int compareTo(Person other) {
if (!(other instanceof Person)) {
throw new IllegalArgumentException();
}
return this.id - ((Person)other).id;
}
}
Outputs :
[Person<10>, Person<9>, Person<8>, Person<7>, Person<6>, Person<5>, Person<4>, Person<3>, Person<2>, Person<1>]
[Person<1>, Person<2>, Person<3>, Person<4>, Person<5>, Person<6>, Person<7>, Person<8>, Person<9>, Person<10>]

Categories

Resources