Internal working of Tree Set Or Difference between HashSet and TreeSet - java

For TreeSet Sorting for mutable object :
If I don't override hashcode equals then for an object having same value for all the fields will be treated as two different object in set as( default objects class hashcode method calculate the hash value of the memory locatuion). So why it is different for the TreeSet. See the below Example.
If I just copy a whole Set into a treeSet then why sorting is not happning.
.
public class Student {
private int id;
private String name;
private int marks;
public Student(int id, String name, int marks) {
super();
this.id = id;
this.name = name;
this.marks = marks;
}
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 int getMarks() {
return marks;
}
public void setMarks(int marks) {
this.marks = marks;
}
#Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", marks=" + marks + "]";
}
public static Comparator<Student> idComparator = new Comparator<Student>() {
#Override
public int compare(Student o1, Student o2) {
return (new Integer(o1.getId())).compareTo(o2.getId());
}
};
public static Comparator<Student> nameComparator = new Comparator<Student>() {
#Override
public int compare(Student o1, Student o2) {
return o1.getName().compareTo(o2.getName());
}
};
/*#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + marks;
result = prime * result + ((name == null) ? 0 : name.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;
Student other = (Student) obj;
if (id != other.id)
return false;
if (marks != other.marks)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}*/
}
.
public class TestMain {
public static void main(String[] args) {
Student s1 = new Student(1, "A", 50);
Student s2 = new Student(1, "A", 50);
Student s3 = new Student(2, "B", 51);
Student s4 = new Student(3, "B", 51);
Student s5 = new Student(4, "B", 41);
Student s6 = new Student(5, "B", 61);
Student s7 = new Student(6, "C", 51);
Student s8 = new Student(7, "D", 46);
Student s9 = new Student(8, "B", 55);
Student s10 = new Student(9, "E", 51);
List<Student> studentList = new ArrayList<>();
studentList.add(s1);
studentList.add(s2);
studentList.add(s3);
studentList.add(s4);
studentList.add(s5);
studentList.add(s6);
studentList.add(s7);
studentList.add(s8);
studentList.add(s9);
studentList.add(s10);
studentList.add(s1);
studentList.add(s2);
studentList.add(s3);
studentList.add(s4);
System.out.println("List Initial Size: " + studentList.size());
List<Student> studentListAfterFilter = studentList.stream()
.filter(p -> p.getMarks() >= 45 && p.getMarks() <= 55).map(p -> p).collect(Collectors.toList());
System.out.println("After filtering List Size: " + studentListAfterFilter.size());
Set<Student> studentSetAfterFilter = studentList.stream().filter(p -> p.getMarks() >= 45 && p.getMarks() <= 55)
.map(p -> p).collect(Collectors.toSet());
System.out.println("After filtering Set Size: " + studentSetAfterFilter.size());
for(Student student:studentSetAfterFilter){
System.out.println("Set Objects: "+student.toString());
}
Set<Student> studentTreeSetAfterFilter=new TreeSet<>(Student.nameComparator);
studentTreeSetAfterFilter.add(s1);
studentTreeSetAfterFilter.add(s2);
studentTreeSetAfterFilter.add(s3);
studentTreeSetAfterFilter.add(s4);
studentTreeSetAfterFilter.add(s5);
studentTreeSetAfterFilter.add(s6);
studentTreeSetAfterFilter.add(s7);
studentTreeSetAfterFilter.add(s8);
studentTreeSetAfterFilter.add(s9);
studentTreeSetAfterFilter.add(s10);
studentTreeSetAfterFilter.add(s1);
studentTreeSetAfterFilter.add(s2);
studentTreeSetAfterFilter.add(s3);
studentTreeSetAfterFilter.add(s4);
for(Student student:studentTreeSetAfterFilter){
System.out.println("TreeSet Objects: "+student.toString());
}
}
}

Related

Iterate List based on condition Set Values to another object

Iterate List based on condition Set Values to another object using Java 8?
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Demo {
public static void main(String[] args) {
// TODO: Condition is => Only if id = 100, then assign internalMarks to (externalMarks + internalMarks); to 103
// So internalMarks = 0 and externalMarks = 500+250=750
List<Employee> employees = Arrays.asList(
new Employee(100, 500, "John", 250),
new Employee(101, 500, "Jane", 250),
new Employee(102, 500, "Jack", 250),
new Employee(103, 500, "Mike", 250)
);
List<Employee> newList = new ArrayList<>();
employees.stream().forEach(e -> {
if(e.getId() == 100 && e.getId() > 0) {
e.setExternalMark(0);
newList.add(e);
}else {
newList.add(e);
}
});
System.out.println(newList);
}
static class Employee {
private int id;
private int internalMark;
private String name;
private int externalMark;
public Employee() {
}
public Employee(int id, int internalMark, String name, int externalMark) {
super();
this.id = id;
this.internalMark = internalMark;
this.name = name;
this.externalMark = externalMark;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getInternalMark() {
return internalMark;
}
public void setInternalMark(int internalMark) {
this.internalMark = internalMark;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getExternalMark() {
return externalMark;
}
public void setExternalMark(int externalMark) {
this.externalMark = externalMark;
}
#Override
public String toString() {
return "Employee [id=" + id + ", internalMark=" + internalMark + ", name=" + name + ", externalMark="
+ externalMark + "]";
}
}
}
//Condition is => Only if id = 100, then assign internalMarks to (externalMarks + internalMarks); to 103
// So internalMarks = 0 and externalMarks = 500+250=750
From your condition, as its slighlty unclear that externalMarks should be changes for Id=100 or Ids 100 to 103, means for all Employees
Take one scenario, where externalMarks should be changes for id = 100, then solution can be
List<Employee> newList1 = employees.stream()
.map(e-> {
if(e.getId() == 100) {
e.setExternalMark(e.getInternalMark()+e.getExternalMark());
e.setInternalMark(0);
}
return e;
})
.collect(Collectors.toList());
For other scenario, where externalMarks should be changes for id = 100 to 103, then solution can be
List<Employee> newList1 = employees.stream()
.map(e-> {
e.setExternalMark(e.getInternalMark()+e.getExternalMark());
e.setInternalMark(0);
return e;
})
.collect(Collectors.toList());

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

How to pass node as a parameter

I have a custom linked list that has node objects of class Student. There are two recursive methods called countNodesRec(Node list) & worstStudentRec(Node List) that both need node object as a parameter.
list1.worstStudentRec(?????)
list1.countNodesRec(????)
Parameters I tried already that have given me errors
list1.list
list1
Not sure what to put there, please help!
Test Class
public class TestList {
public static void main(String[] args) {
Student s1 = new Student("Adams", 3.9, 26);
Student s2 = new Student("Lewis", 2.1, 29);
Student s3 = new Student("Lopez", 4.0, 53);
Student s4 = new Student("Smith", 3.2, 22);
Student s5 = new Student("Zeeler", 3.6, 38);
LinkedList list1 = new LinkedList();
LinkedList list2 = new LinkedList();
LinkedList list3 = new LinkedList();
//1
list1.addFront(s1);
list1.addFront(s2);
list1.addFront(s3);
list1.addFront(s4);
list1.addFront(s5);
list1.printLinkedList();
System.out.println("Worst Student" + list1.worstStudentRec());
System.out.println("Number of Students" + list1.countNodesRec());
}
}
Student Class
public class Student
{
private String lastName;
private double gpa;
private int age;
public Student(String lastName, double gpa, int age)
{
this.lastName = lastName;
this.gpa = gpa;
this.age = age;
}
public int compareTo(Student s)
{
if (gpa < s.gpa)
{
return -1;
}
else if (gpa > s.gpa)
{
return 1;
}
else
{
return 0;
}
}
public String toString()
{
return lastName + "\t" + gpa + "\t" + age;
}
public double getGpa()
{
return gpa;
}
}
Linked List Class
public class LinkedList
{
private class Node
{
public Student data;
public Node next;
public Node(Student s)
{
data = s;
next = null;
}
}
private Node list;
public LinkedList()
{
list = null;
}
public Student bestStudent()
{
Student bestStudent, bstStu;
Node current;
if (list == null)
{
return bestStudent = null;
}
else
{
current = list;
bstStu = new Student("", 0.00, 0);
while (current != null)
{
if (bstStu.getGpa() <= current.data.getGpa())
{
bstStu = current.data;
}
current = current.next;
}
bestStudent = bstStu;
}
return bestStudent;
}
public int countNodesRec(Node list)
{
if(list == null)
{
return 0;
}
else
{
return 1 + countNodesRec(list.next);
}
}
public Student worstStudentRec(Node list)
{
if (list == null)
{
return null;
}
else if (list.next == null)
{
return list.data;
}
Student worstStudent = worstStudentRec(list.next);
return (list.data.compareTo(worstStudent) <= 0) ? list.data : worstStudent;
}
}
You can create a getList method in Linked List class, then call the method in main:
list1.worstStudentRec(list1.getList ())
list1.countNodesRec(list1.getList ())

Compare two array lists in java

I have two different arrays oldUsers and newUsers containing instances of the class User. User contain firstname, lastname and age attributes. I want to know the number of oldUsers objects in the newUsers array that have the same attributes. Shall I use two for loops and compare the arrays one per one or is there a function that can do the same work ?
You first need to override equals() and hashCode(). Then you can implement an intersection() method.
Number of identical values: 2
------------------------------
- { 'firstname': 'Bob', 'lastname': 'Smith', 'age': 30 }
- { 'firstname': 'Robert', 'lastname': 'Brown', 'age': 51 }
Main
import java.util.*;
public class Main {
public static void main(String[] args) {
List<User> oldUsers = new ArrayList<User>();
List<User> newUsers = new ArrayList<User>();
List<User> intersect;
oldUsers.addAll(Arrays.asList(
new User("Bob", "Smith", 30),
new User("Tom", "Jones", 42),
new User("Robert", "Brown", 51),
new User("James", "Jones", 28)
));
newUsers.addAll(Arrays.asList(
new User("Robert", "Brown", 51), // Same
new User("Bob", "Smith", 30), // Same
new User("Tom", "Jones", 21),
new User("James", "Hendrix", 28)
));
intersect = intersection(oldUsers, newUsers);
System.out.printf("Number of identical values: %d%n%s%n",
intersect.size(), "------------------------------");
for (User user : intersect) {
System.out.printf("- %s%n", user);
}
}
// http://stackoverflow.com/a/5283123/1762224
public static <T> List<T> intersection(List<T> list1, List<T> list2) {
List<T> list = new ArrayList<T>();
for (T t : list1) {
if (list2.contains(t)) {
list.add(t);
}
}
return list;
}
}
User
public class User {
private String firstname;
private String lastname;
private int age;
public String getFirstname() { return firstname; }
public void setFirstname(String firstname) { this.firstname = firstname; }
public String getLastname() { return lastname; }
public void setLastname(String lastname) { this.lastname = lastname; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public User(String firstname, String lastname, int age) {
super();
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((firstname == null) ? 0 : firstname.hashCode());
result = prime * result + ((lastname == null) ? 0 : lastname.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;
User other = (User) obj;
if (age != other.age) return false;
if (firstname == null) {
if (other.firstname != null) return false;
} else if (!firstname.equals(other.firstname)) return false;
if (lastname == null) {
if (other.lastname != null) return false;
} else if (!lastname.equals(other.lastname)) return false;
return true;
}
#Override
public String toString() {
return String.format("{ 'firstname': '%s', 'lastname': '%s', 'age': %d }",
firstname, lastname, age);
}
}
Alternative Methods
Set :: Retain All
public static <T> List<T> intersection(List<T> list1, List<T> list2) {
Set<T> set = new HashSet<T>(list1);
set.retainAll(new HashSet<T>(list2));
return new ArrayList<T>(set);
}
List :: Java 8 Filter Stream
public static <T> List<T> intersection(Collection<T> list1, Collection<T> list2) {
return list1.stream().filter(item -> list2.contains(item)).collect(Collectors.toList());
}
Assuming your User objects correctly implement equals() and hashCode(), I would use one of the lists' retainAll(Collection other) method to craft the intersection of both lists and then return its size.
If you have equals() and hashCode() implemented correctly, you can place all inputs from oldUsers array to Set and then check data from newUsers if they are in that Set or not. This will work in O(max(n, m)) (place data in Set is O(n), check newUsers if they are in Set is O(m), so you have O(n) + O(m) = O(max(n,m)), where n is size of oldUsers list and m is size of newUsers list).
For example:
private int numberOfSameUsers(ArrayList<User> oldUsers, ArrayList<User> newUsers) {
Set<User> oldUsersSet = new HashSet<>(oldUsers);
int counter = 0;
for (int i = 0; i < newUsers.size(); i++) if (oldUsersSet.contains(newUsers.get(i))) counter++;
return counter;
}

HazelCast: SqlPredicate issue

I am new to using HazelCast. I have a map of key and value, value being a list of objects. I am trying to use SqlPredicate on the map to filter the values.
Code Snippet:
private void testHazelCast() {
final Employee e1 = new Employee("A", 20, 30);
final Employee e2 = new Employee("C", 25, 45);
final Employee e3 = new Employee("B", 30, 35);
final Employee e4 = new Employee("F", 35, 30);
final Employee e5 = new Employee("E", 40, 40);
final Employee e6 = new Employee(null, 40, 20);
final Employee e7 = new Employee("F", 60, 55);
List<Employee> employeeList_1 = new ArrayList<Employee>() {{add(e1);add(e2);}};
List<Employee> employeeList_2 = new ArrayList<Employee>() {{add(e3);add(e4);add(e7);}};
List<Employee> employeeList_3 = new ArrayList<Employee>() {{add(e5);}};
List<Employee> employeeList_4 = new ArrayList<Employee>() {{add(e6);}};
IMap<Integer, List<Employee>> map = hazelcast.getMap("employee");
map.put(1, employeeList_1);
map.put(2, employeeList_2);
map.put(3, employeeList_3);
map.put(4, employeeList_4);
// EntryObject e = new PredicateBuilder().getEntryObject();
// Predicate predicate_1 = e.get("name").equal("A");
Predicate predicate = new SqlPredicate("name = A");
Set<List<Employee>> employeeSet = (Set<List<Employee>>) map.values(predicate_1);
}
class Employee implements Serializable {
String name;
int age;
int weight;
public Employee(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Name: " + name + ", ");
sb.append("Age: " + age + ", ");
sb.append("Weight: " + weight);
return sb.toString();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
if (age != employee.age) return false;
if (weight != employee.weight) return false;
if (!name.equals(employee.name)) return false;
return true;
}
#Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
result = 31 * result + weight;
return result;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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;
}
}
While executing the above code, I am getting an exception:
Caused by: java.lang.IllegalArgumentException: There is no suitable accessor for 'name' on class 'class java.util.ArrayList'
Could you somebody let me know what exactly I am doing wrong. I understand that it's trying to find the "name" element in the List class.
Is there anyway that I can use SqlPredicate to filter the values ?
Thanks,
Rahul
A predicat is executed on each value of a map. In your example, your map has a Collection of Employee as values, so the predicat is executed on this collection.
Your predicat evaluate to "a collection with name = A" : This is not valid, because a collection doesn't have a name.
In Hazelcast 3.6, you have a notion of 'custom attribute' and ValueExtractor. You can :
Create a class, which own a collection of employee
Link this class to a ValueExtractor which collect the names of each employe in a custom attribute 'name'
see: http://docs.hazelcast.org/docs/3.6/manual/html-single/index.html#custom-attributes
Moreover, having a map of collection is not very efficient.

Categories