I am trying to use SqlPredicate using hazelcast.
Code snippet:
private void testHazelCast() {
HazelcastInstance hazelcast = Hazelcast.newHazelcastInstance();
Employee e1 = new Employee("A", 20, 30);
Employee e2 = new Employee("C", 25, 45);
Employee e3 = new Employee("B", 30, 35);
Employee e4 = new Employee("F", 35, 30);
Employee e5 = new Employee("E", 40, 40);
Employee e6 = new Employee(null, 40, 20);
IMap<Employee, String> map = hazelcast.getMap("employee");
map.put(e1, "e1");
map.put(e2, "e2");
map.put(e3, "e3");
map.put(e4, "e4");
map.put(e5, "e5");
map.put(e6, "e6");
EntryObject e = new PredicateBuilder().getEntryObject();
Predicate predicate = new SqlPredicate(String.format("name = A"));
Set<Employee> employeeSet = map.keySet(predicate);
System.out.println(employeeSet);
}
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 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;
}
}
When I run this, I am getting the following execption:
Caused by: java.lang.IllegalArgumentException: There is no suitable accessor for 'name' on class 'class java.lang.String'
at com.hazelcast.query.impl.ReflectionHelper.createGetter(ReflectionHelper.java:150)
... 14 more
I need to filter the keys using the SqlPredicate and then retrieve the values using the keys. I have achieved this using PredicateBuilder.
Predicate predicate = e.key().get("name").equal("A");
I was trying to perform the same activity using the SqlPredicate.
Can anybody please point out where exactly I am doing wrong with SqlPredicate ?
Thanks,
Rahul
You are supposed to apply the predicate on values of the map, so try to use the IMap with String keys and Employee values
Related
Question : Create a two objects of class Employee and check both are same or diffrent
Below code gives an error : Exception in thread "main" java.util.InputMismatchException
Only object e1 accepts values
class Employee {
String name;
int age;
char gender;
public Employee() {
super();
}
public Employee (String name, int age, char gender) {
this.gender = gender;
this.name = name;
this.age = age;
}
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 char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
}
public class Source {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Employee e1 = new Employee();
//e1.name = sc.nextLine();
//e1.age = sc.nextInt();
//e1.gender = sc.next().charAt(0);
System.out.println(e1.name+" "+e1.age+" "+e1.gender);
Employee e2 = new Employee();
//e2.name = sc.nextLine();
//e2.age = sc.nextInt();
//e2.gender = sc.next().charAt(0);
System.out.println(e2.name+" "+e2.age+" "+e2.gender);
boolean isSame = e1.equals(e2);
if(e1.equals(e2)) {
System.out.println("Same");
}
else {
System.out.println("Different");
}
}
}
How to take user input or input from keyboard for objects e1 and e2?
I have made some changes to your Employee and Source classes, take a look.
public class Source {
Scanner sc = null;
public static void main(String[] args) {
Source source = new Source();
Employee e1 = source.getEmployee();
Employee e2 = source.getEmployee();
if(e1.equals(e2)) {
System.out.println("Same");
}
else {
System.out.println("Different");
}
source.closeScanner();
}
public Source() {
sc = new Scanner(System.in);
}
public void closeScanner() {
sc.close();
}
public Employee getEmployee() {
Employee e = new Employee();
System.out.print("Enter Name: ");
e.name = sc.next();
System.out.print("Enter Age: ");
e.age = sc.nextInt();
System.out.print("Enter Gender: ");
e.gender = sc.next().charAt(0);
System.out.println(e.getName() + " " + e.getAge() + " " + e.getGender());
return e;
}
}
public class Employee {
String name;
int age;
char gender;
public Employee() {
super();
int age = -1;
}
public Employee (String name, int age, char gender) {
this.gender = gender;
this.name = name;
this.age = age;
}
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 char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + gender;
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;
Employee other = (Employee) obj;
if (age != other.age)
return false;
if (gender != other.gender)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Please note that I've added the following two methods
public int hashCode()
and
public boolean equals(Object obj)
to make it possible to compare the two instances of the employee object
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
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;
}
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.
I have an employee class & a client class. I am able to sort using compareTo() via Employee's id & age as they are of integer type. But how do I sort by employee's name or salary?
compareTo is not accepting any data type other than int, throws a compile time exception.
public class Employee implements Comparable<Employee> {
private int id;
private String name;
private int age;
private long salary;
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public long getSalary() {
return salary;
}
public Employee(int id, String name, int age, int salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
#Override
public int compareTo(Employee emp) {
//let's sort the employee based on id in ascending order
//returns a negative integer, zero, or a positive integer as this employee id
//is less than, equal to, or greater than the specified object.
return (this.age - emp.age);
}
#Override
//this is required to print the user friendly information about the Employee
public String toString() {
return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
this.salary + "]";
}
}
Client class
import java.util.Arrays;
public class Test {
public static void main(String a[]){
//sorting custom object array
Employee[] empArr = new Employee[4];
empArr[0] = new Employee(10, "Mikey", 25, 10000);
empArr[1] = new Employee(20, "Arun", 29, 20000);
empArr[2] = new Employee(5, "Lisa", 35, 5000);
empArr[3] = new Employee(1, "Pankaj", 32, 50000);
//sorting employees array using Comparable interface implementation
Arrays.sort(empArr);
System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));
}
}
I just googled seems like I can also achieve it by implementing comparator
public static Comparator<Employee> SalaryComparator = new Comparator<Employee>() {
#Override
public int compare(Employee e1, Employee e2) {
return (int) (e1.getSalary() - e2.getSalary());
}
};
Which one is advisable using the comparator or
#Override
public int compareTo(Employee emp) {
// compare salaries, using the builtin Long.compare:
return Long.compare (salary, emp.salary);
}
If you want to sort based on name, you can try
#Override
public int compareTo(Employee emp) {
return this.name.compareTO(emp.name);
}
Basically, you want to sort your class based on several properties. The trick here is to decide the order in which they should be evaluated, and treat one as a Comparable on its own right. If the comparison isn't 0 - you found which instance should come before the other, and you can just return the value. If not, you need to evaluate a different property.
E.g., assuming the properties you want to use are id, age, name and salary:
#Override
public int compareTo(Employee emp) {
// compare IDs:
int cmp = Integer.compare(id, emp.id);
if (cmp != 0) {
return cmp;
}
// compare ages:
cmp = Integer.compare(age, emp.age);
if (cmp != 0) {
return cmp;
}
// compare names. Luckily, Strings are comparable:
cmp = name.compareTo(emp.name);
if (cmp != 0) {
return cmp;
}
// compare salaries, using the builtin Long.compare:
return Long.compare (salary, emp.salary);
}
I would implement compareTo this way:
public int compareTo(Employee emp) {
return Integer.compare(this.age, emp.age);
}