This is my Car class:
public class Car {
private int FGNr;
private String name;
private String type;
private Owner owner;
private static ArrayList<Integer> allCarIds = new ArrayList<>();
public Car(int FGNr, String name, String type, Owner o) throws Exception {
setFGNr(FGNr);
setName(name);
setType(type);
setOwner(o);
}
public int getFGNr() {
return FGNr;
}
public void setFGNr(int FGNr) throws Exception{
this.FGNr = FGNr;
if(allCarIds.contains(this.FGNr))
throw new Exception("FGNr already excists!! ");
allCarIds.add(this.FGNr);}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Owner getOwner() {
return owner;
}
public void setOwner(Owner owner) throws Exception{
owner.addCar(this);
this.owner = owner;
}
#Override
public int hashCode() {
int hash = 7;
hash = 73 * hash + this.FGNr;
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Car other = (Car) obj;
if (this.FGNr != other.FGNr) {
return false;
}
return true;
}
#Override
public String toString() {
return "Car{" + "FGNr=" + FGNr + ", name=" + name + ", type=" + type + ", owner=" + owner + '}';
}
}
And this is my Owner class:
public class Owner {
private String SVNr;
private String name;
HashSet<Car> allCars = new HashSet<>();
private static ArrayList<String> allOwnerSVNs = new ArrayList<>();
public Owner(String SVNr, String name) throws Exception{
setSVNr(SVNr);
setName(name);
}
public void addCar(Car c) throws Exception{
if(allCars.contains(c))
throw new Exception("this user has already this car");
if(c.getOwner()!=null)
throw new Exception("this car belongs to other owner");
c.setOwner(this);
allCars.add(c);
}
public String getSVNr() {
return SVNr;
}
public void setSVNr(String SVNr) throws Exception{
this.SVNr = SVNr;
if(allOwnerSVNs.contains(this.SVNr))
throw new Exception("SVNg already excists!! ");
allOwnerSVNs.add(this.SVNr);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HashSet<Car> getAllCars() {
return allCars;
}
#Override
public int hashCode() {
int hash = 5;
hash = 41 * hash + Objects.hashCode(this.SVNr);
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Owner other = (Owner) obj;
if (!Objects.equals(this.SVNr, other.SVNr)) {
return false;
}
return true;
}
#Override
public String toString() {
return "Owner{" + "SVNr=" + SVNr + ", name=" + name + ", allCars=" + allCars + '}';
}
}
And this is my main:
try {
Owner o1 = new Owner("0001","Owner1");
Owner o2 = new Owner("0002","Owner2");
Car c1 = new Car(1,"Model S", "Tesla",o1);
Car c2 = new Car(2,"Model 3", "Tesla",o2);
Car c3 = new Car(3,"TT", "Audi",o2);
} catch (Exception ex) {
System.out.println("error:"+ex.getMessage());
}
So when trying to create a new Car I get this error:
Exception in thread "main" java.lang.StackOverflowError
at java.util.HashMap.containsKey(HashMap.java:595)
at java.util.HashSet.contains(HashSet.java:203)
at pkgData.Owner.addCar(Owner.java:28)
at pkgData.Car.setOwner(Car.java:63)
...........
It is a recursion error, but I don't know how to fix it. If I create a new car obviously I have to add the Car to the owner arrayList of cars. and if I call the addCar function the function calls the getOwner function. It's an endless circle of calling.
How I can make sure that when creating a new car that the collection of the owner will also be changed. It would not make any sense that a car has an owner but the owner of the car does not the car in his collection.
These two functions fall an infinite loop as you see.
In Car class
public void setOwner(Owner owner) throws Exception{
owner.addCar(this);
this.owner = owner;
}
And in Owner Class
public void addCar(Car c) throws Exception{
if(allCars.contains(c))
throw new Exception("this user has already this car");
if(c.getOwner()!=this && c.getOwner()!=null)
throw new Exception("this car belongs to other owner");
c.setOwner(this);
allCars.add(c);
}
The car sets its owner and sends itself to the Owner class' addCar() method, thats OK. However, why the Owner class' addCar() method sets the owner as itself again ?
I think there is a logical mistake. If you remove c.setOwner(this) line, it works fine.
Usually adding element to a container should be done in the container itself.
In you example Owner is the container and Car is the element.
As an example see java.awt.Container and java.awt.Component.
Don't call owner.addCar(this); from the Car.setOwner.
Let the Owner add the car to the list (which you already do) and set itself as owner to the Car.
public void setOwner(Owner owner) throws Exception{
owner.addCar(this); //remove this line
this.owner = owner;
}
Related
I have actually a problem on a Set in my project (code below)
public static Set<BeanObject> mapToSetBean(Collection<Object> listModel) {
Set<BeanObject> listToReturn = new HashSet<>();
for (Iterator<Object> iterator = listModel.iterator(); iterator.hasNext();) {
Object model = iterator.next();
BeanObject bean = new BeanObject();
bean = mapToBean(model);
listToReturn.add(bean);
}
return listToReturn;
}
When some beans are added to the list they replace another one.
For example:
List{}
add object1 / List{object1}
add object2 / List{object1, object2}
add object1 / List{object1, object2, object3}
add object4 / List{object4, object2, object3}
The equals and the hashcode of the object are override the hashcode are all different and in debug mode we don't enter in the override equals.
When I use an ArrayList everything works but I prefer not to change the type it has a huge impact on my project.
---------------- EDIT ---------------
public static BeanObject mapToBean(Object model) {
BeanObject bean = new BeanObject();
if (model != null) {
bean.setId(model.getId());
if(model.getId() != null){
bean.setIdString(model.getId().toString());
}
if (model.getName() != null) {
bean.setName(model.getName().toLowerCase());
}
bean.setActif(model.getActif());
if (model.getShortName() != null) {
bean.setShortName(model.getShortName().toUpperCase());
}
}
return bean;
}
BeanObject
public class BeanObject implements Comparable<BeanObject> {
/**
* serial
*/
private static final long serialVersionUID = 1L;
private BigInteger id;
private String name;
private String shortName;
private Short actif;
private String idString;
public BeanObject() {
}
public BeanObject(BigInteger id, String libelle) {
this.id = id;
this.name = libelle;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (!(o instanceof BeanObject)) {
return false;
}
BeanObject other = (BeanObject) o;
boolean result;
if (null == this.id) {
if (null == other.id) {
result = true;
} else {
result = false;
}
} else {
result = this.id.equals(other.id);
}
return result;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
return this.id.intValue() * name.hashCode() * shortName.hashCode();
}
public BigInteger getId() {
return id;
}
public void setId(BigInteger id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public Short getActif() {
return actif;
}
public void setActif(Short actif) {
this.actif = actif;
}
public String getIdString() {
return idString;
}
public void setIdString(String idString) {
this.idString = idString;
}
}
Are you certain the BeanObject's hashcode values are unique? That hashcode method seems like it would map a lot of objects to 0 if any of its fields hashed to 0 since it is straight multiplication. I would suggest updating to a more standardized approach for it like the following:
#Override
public int hashCode() {
return Objects.hash(id, name, shortName);
}
Objects.hash is from the java.util package.
If this still doesn't solve the problem, I would double check the hashcode results for each bean object at add time.
I have an below object
class CustomObj{
private String name;
private String dept;
public String getName(){
return this.name;
}
public String getDept(){
return this.dept;
}
private CustomObj(){
}
private CustomObj(CustomObjBuilder builder){
this.name = builder.name;
this.dept= builder.dept;
}
#Override
public boolean equals(Object o) {
if (o == this) return true;
if (o == null || getClass() != o.getClass()) return false;
CustomObj that = (CustomObj) o;
return that.name.equals(name) &&
that.dept.equals(dept);
}
#Override
public int hashCode() {
int result = 31;
result = 31 * result + name.hashCode();
result = 31 * result + dept.hashCode();
return result;
}
public static class CustomObjBuilder{
private String name;
private String dept;
public CustomObjBuilder(String name, String dept){
this.name = name;
this.dept = dept;
}
public CustomObjBuilder setName(String name){
this.name = name;
return this;
}
public CustomObjBuilder setDept(String dept){
this.dept = dept;
return this;
}
public CustomObj build(){
return new CustomObj(this);
}
}
}
and class that uses above
class XYZ{
Set<CustomObj> obj = new HashSet<CustomObj>();
public void process(String a, String b){
CustomObj o = new CustomObj.CustomObjBuilder(a,b).build();
if(!obj.contains(o)){
obj.add(o);
}
}
}
And a test class
class TestXYX{
#Test
public void test(){
XYZ xyz = new XYZ();
xyz.process("TEST","TESTABC");
xyz.process("TEST","TESTABC");
}
}
Beacuse I have overrideen hascode and equals, both the above are equal and when process is called second time, the control should not go into if(!obj.contains(o)) second time and size of the set should be 1. But when i run the test obj.add(o); is called two times. But the values of both this object and that objec inside equals methods are same, but
that.name.equals(name) && that.dept.equals(dept)
inside CustomObj returns false. Can someone please help me understand why?
The code is fine. To verify add an sysout to check Set size:
class XYZ {
Set<CustomObj> obj = new HashSet<CustomObj>();
public void process(String a, String b) {
CustomObj o = new CustomObj.CustomObjBuilder(a, b).build();
if (!obj.contains(o)) { // Fails second time for your use case.
obj.add(o);
}
System.out.println(obj.size()); // This is 1 in your use case.
}
}
I want to create my own custome predicate to compare composite id's inside object. The need is to because i have to write specific date comparison logic on object inside object (composite id). I don't want to compare individual attributes.i want to use composite id because it comes from invoker and I can't get result using Predicate.in and Predicate.equals
My Object structure is like below
Birth{id=BirthId{name='b3', dob=Wed Jan 01 10:53:20 IST 1902}, name='b3', dob=Wed Jan 01 10:53:20 IST 1902, description='MNP'}
and inside IMap it is stored like below
key : BirthId{name='b3', dob=Wed Jan 01 10:53:20 IST 1902}
value : Birth{id=BirthId{name='b3', dob=Wed Jan 01 10:53:20 IST 1902}, name='b3', dob=Wed Jan 01 10:53:20 IST 1902, description='MNP'}
My Java Classes(Birth and Birthid) Structure is below
public class Birth implements Serializable, Portable {
private static final long serialVersionUID = 1L;
private BirthId id;
private String name;
private Date dob;
private String description;
public BirthId getId() {
return id;
}
public void setId(BirthId id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public int hashCode() {
return (new HashCodeBuilder()).append(this.id).append(this.name).append(this.dob).toHashCode();
}
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (!(other instanceof Birth)) {
return false;
} else {
Birth rhs = (Birth) other;
return (new EqualsBuilder()).append(this.id, rhs.id).append(this.name, rhs.name).append(this.dob, rhs.dob).isEquals();
}
}
#Override public String toString() {
return "Birth{" + "id=" + id + ", name='" + name + '\'' + ", dob=" + dob + ", description='" + description + '\'' + '}';
}
public int getFactoryId() {
return 1;
}
public int getClassId() {
return 1;
}
public void writePortable(PortableWriter portableWriter) throws IOException {
portableWriter.writePortable("idComposite", getId());
portableWriter.writeUTF("id", getId().toString());
portableWriter.writeUTF("name", getName());
portableWriter.writeUTF("description", getDescription());
Date date = getDob();
portableWriter.writeLong("dob", ((date == null) ? -1 : date.getTime()));
}
public void readPortable(PortableReader portableReader) throws IOException {
setId((BirthId) portableReader.readPortable("idComposite"));
setName(portableReader.readUTF("name"));
setDescription(portableReader.readUTF("description"));
long date = portableReader.readLong("dob");
setDob(((date == -1) ? null : new Date(date)));
}
}
public class BirthId implements Comparable<BirthId>, Serializable, Portable {
private static final long serialVersionUID = 1L;
private String name;
private Date dob;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public int hashCode() {
return (new HashCodeBuilder()).append(this.name).append(this.dob).toHashCode();
}
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (!(other instanceof BirthId)) {
return false;
} else {
BirthId rhs = (BirthId) other;
return (new EqualsBuilder()).append(this.name, rhs.name).append(this.dob, rhs.dob).isEquals();
}
}
public int compareTo(BirthId rhs) {
return this == rhs ? 0 : (null == rhs ? -1 : (new CompareToBuilder()).append(this.name, rhs.name).append(this.dob, rhs.dob).toComparison());
}
#Override public String toString() {
return "BirthId{" + "name='" + name + '\'' + ", dob=" + dob + '}';
}
public int getFactoryId() {
return 1;
}
public int getClassId() {
return 2;
}
public void writePortable(PortableWriter portableWriter) throws IOException {
portableWriter.writeUTF("name", getName());
Date date = getDob();
portableWriter.writeLong("dob", ((date == null) ? -1 : date.getTime()));
}
public void readPortable(PortableReader portableReader) throws IOException {
setName(portableReader.readUTF("name"));
long date = portableReader.readLong("dob");
setDob(((date == -1) ? null : new Date(date)));
}
public static ClassDefinition getClassDefinition(int portableVersion) {
ClassDefinitionBuilder result = new ClassDefinitionBuilder(1, 2, portableVersion);
result.addUTFField("name");
result.addLongField("dob");
return result.build();
}
}
I have created own custom Predicate to compare dates like below
public class DatePredicate extends AbstractPredicate<Comparable, BirthId> {
Comparable[] values;
private volatile Set<Comparable> convertedInValues;
public DatePredicate() {
}
public DatePredicate(String attribute, Comparable... values) {
if (values == null) {
throw new NullPointerException("Array can't be null");
} else {
this.values = values;
}
}
protected boolean applyForSingleAttributeValue(Map.Entry entry, Comparable attributeValue) {
//My own date comparison logic
return true;
}
public int getId() {
return 99;
}
}
Caller code is
Predicate p = new DatePredicate("id", new BirthId("12345",passSpecifiedDate()));
Result res = imap.values(p);
I am getting below error
Exception in thread "main" com.hazelcast.nio.serialization.HazelcastSerializationException: com.hazelcast.internal.serialization.impl.ArrayDataSerializableFactory#5f007be3 is not be able to create an instance for id: 99 on factoryId: -32
I do not know the best way to create own custom predicate and hazelcast doc does not specify the also.
Could any please guide me how to do this?
#oomph-fortuity, your DatePredicate extends AbstractPredicate which implements IdentifiedDataSerializable and used by built-in Hazelcast predicates. Built-in Predicate Serializable Factory try to deserialize your class & fails since it only knows how to serialize/deserialize built-in Predicates.
Instead, just implement com.hazelcast.query.Predicate interface:
class DatePredicate implements Predicate<BirthId, Birth> {
BirthId birthIdToCompare;
public DatePredicate() {
}
public DatePredicate(BirthId birthId) {
this.birthIdToCompare = birthId;
}
#Override
public boolean apply(Map.Entry<BirthId, Birth> mapEntry) {
BirthId key = mapEntry.getKey();
///your custom logic
return true;
}
}
And call like this
Predicate p = new DatePredicate(new BirthId("12345",passSpecifiedDate()));
Result res = imap.values(p);
Let me know if that works.
I had an interview today and I have given two java classes and asked to search dog details by registration number. I know that Java.util.ArrayList.contains(Object) but do not know how to implement when there are more than one fields.
The second question was: what is the most efficient search techniques you can use in this example? I thought about Collections.binarySearch but not sure that it is the most efficient in this example. If so, how can I implement it?
DogSort.java
public class DogSort {
public static void main(String[] args) {
ArrayList<Dog> listDog = new ArrayList<Dog>();
Scanner sc = new Scanner(System.in);
listDog.add(new Dog("Max", "German Shepherd", "33"));
listDog.add(new Dog("Gracie","Rottweiler","11"));
Collections.sort(listDog, Dog.COMPARE_BY_NAME);
System.out.println(listDog);
}
}
Dog.java
class Dog {
private String name;
private String breed;
private String registrationNumber;
public Dog(String name, String breed, String registrationNumber) {
this.name = name;
this.breed = breed;
this.registrationNumber = registrationNumber;
}
public static Comparator<Dog> COMPARE_BY_NAME = new Comparator<Dog>() {
public int compare(Dog one, Dog other) {
return one.name.compareTo(other.name);
}
};
//getter and setter methods for all private variable
}
I agree with #Pritam Banerjee's answer. The most efficient search technique is to use HashMap in this scenario. I would recommend to use HashSet but the HashSet#contains method returns boolean, so just use map. Here is the code snippet.
Just for Information When using hash based collection/map dont forget to implement hashCode and equals method properly.
public class DogSearch {
public static void main(String[] args) {
Map<String, Dog> dogs = new HashMap<String, Dog>();
Dog max = new Dog("Max", "German Shepherd", "1001");
Dog gracie = new Dog("Gracie", "Rottweiler", "1002");
Dog luca = new Dog("Luca", "Labrador", "1003");
Dog tiger = new Dog("Tiger", "Beagle", "1004");
Dog meemo = new Dog("Meemo", "Bulldog", "1005");
Dog lacie = new Dog("Lacie", "German Shorthaired Pointer", "1006");
dogs.put(max.getRegistrationNumber(), max);
dogs.put(gracie.getRegistrationNumber(), gracie);
dogs.put(luca.getRegistrationNumber(), luca);
dogs.put(tiger.getRegistrationNumber(), tiger);
dogs.put(meemo.getRegistrationNumber(), meemo);
dogs.put(lacie.getRegistrationNumber(), lacie);
Dog result = dogs.get("1002");
if (result == null) {
System.out.println("Dog not found");
} else {
System.out.println(result);
}
}
}
class Dog {
private String name;
private String breed;
private String registrationNumber;
public Dog(String name, String breed, String registrationNumber) {
this.name = name;
this.breed = breed;
this.registrationNumber = registrationNumber;
}
public static Comparator<Dog> COMPARE_BY_NAME = new Comparator<Dog>() {
public int compare(Dog one, Dog other) {
return one.name.compareTo(other.name);
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getRegistrationNumber() {
return registrationNumber;
}
public void setRegistrationNumber(String registrationNumber) {
this.registrationNumber = registrationNumber;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((breed == null) ? 0 : breed.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((registrationNumber == null) ? 0 : registrationNumber.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;
Dog other = (Dog) obj;
if (breed == null) {
if (other.breed != null)
return false;
} else if (!breed.equals(other.breed))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (registrationNumber == null) {
if (other.registrationNumber != null)
return false;
} else if (!registrationNumber.equals(other.registrationNumber))
return false;
return true;
}
#Override
public String toString() {
return "Dog [name=" + name + ", breed=" + breed + ", registrationNumber=" + registrationNumber + "]";
}
}
Time Complexity
Insertion : O(1)
Search : O(1)
Add it to a HashMap with Registration as Key and Dog object as the value and then search the Map.
O(1) insertion and O(1) searching.
Binary Search O(log n).
For the first question ie to search details by registration number here is the code
import java.util.Comparator;
import java.util.TreeMap;
public class DogSort {
public static void main(String[] args) {
TreeMap<Integer, Dog> listDogs = new TreeMap<>();
listDogs.put(33, new Dog("Max", "German Shepherd", "33"));
listDogs.put(11, new Dog("Gracie", "Rottweiler", "11"));
System.out.println(listDogs);
System.out.println(listDogs.containsKey(11));
System.out.println(listDogs.get(11));
}
}
class Dog {
private String name;
private String breed;
private String registrationNumber;
public Dog(String name, String breed, String registrationNumber) {
this.name = name;
this.breed = breed;
this.registrationNumber = registrationNumber;
}
public static Comparator<Dog> COMPARE_BY_NAME = new Comparator<Dog>() {
public int compare(Dog one, Dog other) {
return one.name.compareTo(other.name);
}
};
#Override
public String toString() {
return "Dog [name=" + name + ", breed=" + breed + ", registrationNumber=" + registrationNumber + "]";
}
}
It is very difficult to get the details of dog by registration number using arraylist, but with map it is quite easy.
And you can override the hashcode and equals method like this but the arraylist compare method works differently.
What you can do is you can write a method which can search details by registration number. The method will have to iterate the list and find the Dog object,and if the list is sorted then you need to implement your own binary search to get the Dog object according to the registration number.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class DogSort {
public static void main(String[] args) {
ArrayList<Dog> listDog = new ArrayList<Dog>();
listDog.add(new Dog("Max", "German Shepherd", "33"));
listDog.add(new Dog("Gracie", "Rottweiler", "11"));
Collections.sort(listDog, Dog.COMPARE_BY_NAME);
System.out.println(listDog);
System.out.println(listDog.contains(new Dog("Max", "Rottweiler", "33")));
}
}
class Dog {
private String name;
private String breed;
private String registrationNumber;
public Dog(String name, String breed, String registrationNumber) {
this.name = name;
this.breed = breed;
this.registrationNumber = registrationNumber;
}
public static Comparator<Dog> COMPARE_BY_NAME = new Comparator<Dog>() {
public int compare(Dog one, Dog other) {
return one.name.compareTo(other.name);
}
};
#Override
public String toString() {
return "Dog [name=" + name + "]";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((registrationNumber == null) ? 0 : registrationNumber.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;
Dog other = (Dog) obj;
if (registrationNumber == null) {
if (other.registrationNumber != null)
return false;
} else if (!registrationNumber.equals(other.registrationNumber))
return false;
return true;
}
}
I'm trying to add an index where my override equals() determines if two objects are the same or not.
Car.java
public static class Car {
final String id;
private String name;
public Car(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static final Attribute<Car, Car> CAR = new SimpleAttribute<Car, Car>() {
#Override
public Car getValue(Car car, QueryOptions queryOptions) {
return car;
}
};
#Override
public String toString() {
return "Car{" + "id=" + id + ", name=" + name + '}';
}
}
Fetcher.java
public static final ResultSet<Car> get(final IndexedCollection<Car> indexedCollection, final Car car) {
return indexedCollection.retrieve(QueryFactory.equal(Car.CAR, car));
}
Main.java
public static void main(String args[]) {
IndexedCollection<Car> cars = new ConcurrentIndexedCollection<>();
cars.addIndex(NavigableIndex.onAttribute(Car.CAR));
}
The problem is on this line cars.addIndex(NavigableIndex.onAttribute(Car.CAR)); where the error message is no suitable method found for onAttribute(Attribute<Car,Car>). Am I doing something wrong here or is there another call I should be using instead?
Remove cars.addIndex(NavigableIndex.onAttribute(Car.CAR));, because it is not really an usefull index... and I think this was not a motivation of the developer. You should create Attributes for CAR_ID and CAR_NAME and create an Query for comparison. In this case I misuse (to achieve what you expect) IndexedCollection as a simple Set. But... here is a possible solution, if I have understood you correctly:
Override equals in Car:
class Car {
private final int id;
private String name;
public Car(int i, String name) {
this.id = i;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(obj == null) return false;
if (!(obj instanceof Car)) return false;
Car car = (Car) obj;
if(car.getId() == this.getId())
if(car.getName().equals(this.getName()))
return true;
return false;
}
public static final Attribute<Car, Car> CAR = new SimpleAttribute<Car, Car>() {
#Override
public Car getValue(Car car, QueryOptions queryOptions) {
return car;
}
};
#Override
public String toString() {
return "Car{" + "id=" + id + ", name=" + name + '}';
}
}
Main:
IndexedCollection<Car> cars = new ConcurrentIndexedCollection<>();
cars.add(new Car(1, "test"));
cars.add(new Car(2, "test2"));
cars.add(new Car(3, "test3"));
Car s = new Car(2, "test2");
ResultSet<Car> cs= cars.retrieve(QueryFactory.equal(Car.CAR, s));
cs.forEach(c -> System.out.println(c.toString()));