I have Set of Object which has existing values and getting a new Set values as an update. If the new Set does contain the old Object then I do nothing, if the new Set contains new Object then I want send create update and if the new Set doesn't contain an existing object then I want send a delete update.
Object has two fields :
private PreferenceType preferenceType;
private String preferenceValue;
Currently I am comparing the existing Set objects against new Set objects and if I don't find any existing object in new set then sending the delete update.
private void sendDeletePreferenceMessage(Set<AccountPreference> existingAccountPreferences, Set<AccountPreference> accountPreferencesFromRequest) {
int counter = 0;
for(AccountPreference accountPreference : existingAccountPreferences) {
for(AccountPreference accountPreference1: accountPreferencesFromRequest) {
if(accountPreference.getPreferenceType().equals(accountPreference1.getPreferenceType()) &&
accountPreference.getPreferenceValue().equals(accountPreference1.getPreferenceValue()))
counter++;
}
if(counter == 0) {
accPrefDeleteSender.send(accountPreference);
}
}
}
And also comparing the new set of objects against existing set of Objects to find the new updates that I want send as a create update
private void sendCreatePreferenceMessage(Set<AccountPreference> accountPreferencesFromRequest, Set<AccountPreference> existingAccountPreferences) {
int counter = 0;
for(AccountPreference accountPreference : accountPreferencesFromRequest) {
for(AccountPreference accountPreference1: existingAccountPreferences) {
if(accountPreference.getPreferenceType().equals(accountPreference1.getPreferenceType()) &&
accountPreference.getPreferenceValue().equals(accountPreference1.getPreferenceValue()))
counter++;
}
if(counter == 0) {
accPrefCreateSender.send(accountPreference);
}
}
}
This works perfectly but I believe this could be simplified in a better way. Any suggestion of doing this better!
You are using two AccountPreference Objects: one with id field, and another without id. I don't know if it's possible without using interfaces or abstract classes. Nevertheless, according to your comments it seems to me you're confused how to override Object.equals method, so I'll give you an example:
class MyObjectWithId {
private long id;
private String someField;
public String getSomeField() {
return someField;
}
#Override
public boolean equals(Object other){
if (this == other) return true;
if (other == null || !other.getClass().isInstance(MyObject.class)) return false;
MyObject myObject = (MyObject) other;
return this.getSomeField().equals(myObject.getSomeField());
}
}
class MyObject {
private String someField;
public String getSomeField() {
return someField;
}
#Override
public boolean equals(Object other){
if (this == other) return true;
if (other == null || !other.getClass().isInstance(MyObjectWithId.class)) return false;
MyObjectWithId myObjectWithId = (MyObjectWithId) other;
return this.getSomeField().equals(myObjectWithId.getSomeField());
}
}
As you can see, you can ask if the two different types of Object are equal (in this case, there isn't need for overriding hashCode).
Now you should be able to do the rest (regarding your original question about two Sets)
Set has a method boolean contains(Object o).
You don't need two for loops, just iterate through one Set and check if another Set contains() the object!
You also need to override the boolean equals(Object o) in the POJO!
class MyObject {
private PreferenceType preferenceType;
private String preferenceValue;
#Override
public boolean equals(Object o){
if (this == o)
return true;
if (o == null || o.getClass()o.getClass() != getClass())
return false;
if(this.getPreferenceType().equals(o.getPreferenceType()) && this.getPreferenceValue().equals(o.getPreferenceValue()))
return true;
return false;
}
}
}
Related
I have these two java classes as below:
RelocationDisabledProduct
public class RelocationDisabledProduct {
#JsonProperty("productIdentifierType")
private ProductIdentifierType productIdentifierType;
#JsonProperty("id")
private String id;
#Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
final Item that = (Item)o;
return Objects.equals(id, that.getId()) &&
Objects.equals(productIdentifierType, that.getProductIdentifierType());
}
#Override
public int hashCode() {
return Objects.hash(id, productIdentifierType);
}
}
Item
public class Item {
private String id;
private ProductIdentifierType productIdentifierType;
}
equals works fine
relocationDisabledProduct.equals(item) // true
but contains does not
List<RelocationDisabledProduct> relocationDisabledProducts;
...
getRelocationDisabledProducts().contains(item) // false
Since contains uses the equals method, not sure why my above syntax returns false?
I believe this is due to the definition of AbstractCollection<E> contains(Object o). The Javadoc says
public boolean contains​(Object o)
Returns true if this collection contains the specified element. More formally, returns true if and only if this collection contains at least one element e such that Objects.equals(o, e).
Note the order of arguments to contains(). It is using the equals() method from Item, not the one from RelocationDisabledProduct, which you would have probably seen if you stepped into the code in the debugger.
Both Item and RelocationDisabledProduct need to share a common equals() implementation, maybe a default method of a superinterface... you'll have to work out what makes sense in your case.
I have a DAOImplementation class with the method definition below.
#Override
public Registration getRegistrationInfoById(int aRegistrationId) {
String SQL = "{CALL getRegistrationInfoById(?)}";
Registration aRegistration = new Registration();
try (Connection con = DBUtil.getConnection(DBType.MYSQL);
CallableStatement cs = con.prepareCall(SQL);) {
cs.setInt(1, aRegistrationId);
try (ResultSet rs = cs.executeQuery();) {
while (rs.next()) {
int gradeLevel = Integer.parseInt(rs.getString(RegistrationTable.GRADELEVEL));
aRegistration.setGradeLevel(gradeLevel);
}
}
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, e.getErrorCode() + "\n" + e.getMessage());
}
return aRegistration;
}//end of method
This returns an integer value of Grade Level (1,2,3,4,5,6,7...so on...) which I've verified because I tried printing the output returned by aRegistration.getGradeLevel();
Now my problem is with my JComboBox. I have set a ListCellRenderer for my JComboBox which holds all the GradeLevel values
public class JComboBoxRenderer_GradeLevel extends JLabel implements ListCellRenderer<Object> {
public JComboBoxRenderer_GradeLevel() {
this.setOpaque(true);
}
#Override
public Component getListCellRendererComponent(JList<? extends Object> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof GradeLevel) {
this.setText("" + ((GradeLevel) value).getGradelevel());
} else {
this.setText("--");
}
if (isSelected) {
this.setBackground(Color.YELLOW);
this.setForeground(list.getSelectionForeground());
} else {
this.setBackground(list.getBackground());
this.setForeground(list.getForeground());
}
return this;
}
}
And looks like this JComboBox as expected. (GradeLevel model is renderered to simply show an int value of gradelevel), ((GradeLevel) value).getGradelevel());returns an integer value.
I understand that even when JComboBox has its renderer that displays an integer value of GradeLevel by using ((GradeLevel)value).getGradeLevel(), the actual value on the JComboBox is still treated as instance of GradeLevel or object. But not a String or int.
So my problem is when I try to set the selected value to an int value, it won't change the selected value of the JComboBox. Nothing happens when I use setSelectedItem();
This is what I tried to do for the GUI.
//Grade Level
GradeLevelDaoImpl gldi = new GradeLevelDaoImpl();
List<GradeLevel> gradeLevels = gldi.getAllGradeLevelsInfo();
DefaultComboBoxModel gradeLevelModel = new DefaultComboBoxModel(gradeLevels.toArray());
jcmbGradeLevel.setModel(gradeLevelModel);
jcmbGradeLevel.setRenderer(new JComboBoxRenderer_GradeLevel());
jcmbGradeLevel.setSelectedIndex(-1);
GradeLevel gradeLevel = new GradeLevel();
gradeLevel.setGradelevel(registration.getGradeLevel());
jcmbGradeLevel.setSelectedItem(gradeLevel); //PROBLEM HERE, it doesn't change
JOptionPane displays this.
JOptionPane.showMessageDialog(null,"GradeLevel: "+gradeLevel);
JOptionPane.showMessageDialog(null,"GradeLevel: "+gradeLevel.getGradeLevel());
It doesn't seem to be able to compare the object I'm trying to set it to(gradeLevel) with the objects JComboBox has(gradeLevels). Notice the singular and plural.
How do I manipulate the types so that setSelectedItem() will match with what the JComboBox have?
Thanks.
If you want to do this by using different instances of the object, but with the same properties, then you need to override the class's equals and hashcode methods, so that the combination of properties are unique. This is very important, this is a relationship expectation that any object which is equal to another will have the same hashcode
This is a really quick example and I used by IDE's auto generation process (because I'm lazy), but, if your Registration class has other properties which should be considered when comparing to instances of the class, you will need to modify it to support them (again, any good IDE should be able to do this)
public class Registration {
private int gradeLevel;
public Registration(int gradeLevel) {
this.gradeLevel = gradeLevel;
}
public int getGradeLevel() {
return gradeLevel;
}
public void setGradeLevel(int gradeLevel) {
this.gradeLevel = gradeLevel;
}
#Override
public int hashCode() {
int hash = 7;
hash = 73 * hash + this.gradeLevel;
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 Registration other = (Registration) obj;
if (this.gradeLevel != other.gradeLevel) {
return false;
}
return true;
}
}
Then using something like...
Registration a = new Registration(1);
Registration b = new Registration(1);
Registration c = new Registration(2);
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(b.equals(c));
will print...
true
false
false
which shows us that the code is working.
Once you get this setup, you should then be able to change the selected item by creating an instance of Registration, seeding it with the required properties and passing it to the JComboBox.
This is very important and very common concept used a lot within Java, well worth taking the time to learn and understand
I have implemented HashMap for storing hotel booking entry.But I'm getting null values on .get(object) method even it contains all keys and returning keys correctly.I already override equals() & hashCode() methods in two different class (bookingSeason & entry) because bookingSeason class is used in some other class also and it works correctly but in entry class it does not work.
public class Entry {
String code;
List<BookingSeason> booking=new ArrayList<>();
public Entry(String code) {
this.code=code;
}
#Override
public boolean equals(Object o) {
if(o==null)
return false;
if(!(o instanceof Entry))
return false;
Entry room=(Entry) o;
return this.code.equals(room.code)&&
this.booking.equals(room.booking);
}
#Override
public int hashCode() {
return Objects.hash(code,booking);
}
}
public class BookingSeason {
LocalDate startDate;
LocalDate endDate;
public BookingSeason(LocalDate startDate,LocalDate endDate) {
this.startDate=startDate;
this.endDate=endDate;
}
#Override
public boolean equals(Object object)
{
if(object==this)
return true;
if(!(object instanceof BookingSeason))
return false;
BookingSeason bS=(BookingSeason) object;
return Objects.equals(startDate,bS.startDate)&& Objects.equals(
endDate,bS.endDate);
}
#Override
public int hashCode() {
return Objects.hash(startDate,endDate);
}
}
public class Hotel {
List<BookingSeason> bookPeriod=new ArrayList<>();
HashMap<Long,Entry> roomEntry =new HashMap<>();
long num;
Entry newRoom=new Entry();
for(int i=101;i<=199;i++) {
num=i;
newRoom.code="A";
newRoom.code=newRoom.code.concat(String.valueOf(i));
roomEntry.put(num,new Entry(newRoom.code));
System.out.println(roomEntry.get(i));
}
}
roomEntry.put(num,new Entry(newRoom.code));
uses the long value num to enter the new Entry object into the hashmap.
System.out.println(roomEntry.get(i));
uses the int value i to try to get the Entry object.
But, since
Long.valueOf(11).equals(Integer.valueOf(11)) == false
it will not found the entry. You need to pass a long/Long value to the get method. Therefore, either using
System.out.println(roomEntry.get(num));
or using
System.out.println(roomEntry.get((long) i));
will solve your problem.
For reference see also What are the reasons why Map.get(Object key) is not (fully) generic
Solution:
Simply change the for loop from this:
for(int i=101;i<=199;i++) {
to this:
for(long i=101;i<=199;i++) {
Explanation:
What you have done wrong here is that you are trying to pass an int into the get method of HashMap<Long, Entry>.
Since the HashMap uses longs as keys, whenever the get method sees you try to use some other type of incompatible value, like int, it just returns null!
Although the integer i you passed into get has the same hash code as the long num, the get method treats them as "not the same".
Why?
Think about what would happen if get allowed you to use an object that is of unrelated type to the key type of the hash map to access a value:
class A {
#Override
public int hashCode() { return 1; }
}
class B {
#Override
public int hashCode() { return 1; }
}
// in some method
HashMap<A, Object> map = new HashMap<>();
map.put(new A(), "some stuff");
map.get(new B()); // returns "someStuff"! makes no sense, right?
I have an Item object having 4 String fields and 3 boolean fields.
I have to construct this object based on the 3 boolean variables.
The target is whenever any one of the boolean variable is true we have to create the object having that/those boolean variable set.
If for any situation none of the boolean variables are true, we wont create the object.
I am using a COR to check whether any of the boolean fields will be set or not based on some business logic.
I was trying this with builder, but then I have to construct so many objects and later discard them when none of the boolean variables found true.
Can anyone have any better idea, to solve this kind of problem ?
Well thanks for the 2 delete flag for this question. Thank for the thoughts on this question as well.
I did something to achieve what I want. Which is quite flexible I believe. Only part if there is a dependency on If loop, but that is acceptable since Report class can have extra boolean so when that class is changed, it's builder should be touched to cater that change. Rest this is flexible which I wanted.
public class Report {
private String acftNo;
private Date plannedDate;
private String plannedStn;
private Integer mntncId;
private Set<String> capableStations;
private String routedStn;
private boolean isRoutedNEQPlannedStn; //Inconsistency type 1
private boolean isCapableAtPlannedStn; //Inconsistency type 2
private boolean isPlannedOrRoutedStationExists; //Inconsistency type 3/5
public Report(String acftNo, Integer mntncId) {
super();
this.acftNo = acftNo;
this.mntncId = mntncId;
}
public Report(String acftNo, Date plannedDate, String plannedStn,
Integer mntncId) {
super();
this.acftNo = acftNo;
this.plannedDate = plannedDate;
this.plannedStn = plannedStn;
this.mntncId = mntncId;
}
//setters and getters. Removed for space.
public static Report buildReport(Maintenance<?> task, Set<InconsistencyReport> enumSet) {
Report temp = new Report(task.getAssignment().getAircraftNumber(),task.getAssignment().getMntncScheduleDate(),
task.getAssignment().getStationCode(),task.getAssignment().getMntncId());
temp.setCapableStations(InconsistencyReport.getCapableStations(task));
for(InconsistencyReport ir : enumSet)
{
if(ir.compareTo(InconsistencyReport.ROUTED_STN_NEQ_PLANNED_STN)==0)
temp.setRoutedNEQPlannedStn(true);
if(ir.compareTo(InconsistencyReport.ITEM_NT_CAPABLE_AT_PLANNED_STN)==0)
temp.setCapableAtPlannedStn(true);
if(ir.compareTo(InconsistencyReport.NO_ROUTD_STN_ON_A_DATE)==0)
temp.setPlannedOrRoutedStationExists(true);
}
return temp;
}
}
calculateInconsitencyReport() method which will decide whether to create object or not.
public class InconsistencyReportChain {
public enum InconsistencyReport implements InconsistencyReportIface {
ROUTED_STN_NEQ_PLANNED_STN {
#Override
public boolean findInconsistency(Maintenance<?> task ) {
if(!validate(task))
return false;
//some logic
return true;
return false;
}
},
ITEM_NT_CAPABLE_AT_PLANNED_STN {
#Override
public boolean findInconsistency(Maintenance<?> task) {
if(!validate(task))
return false;
//some logic
return true;
return false;
}
},
NO_ROUTD_STN_ON_A_DATE {
#Override
public boolean findInconsistency(Maintenance<?> task) {
if(!validate(task))
return false;
//some logic
return true
return false;
}
};
#Override
public boolean validate(Maintenance<?> task) {
return !(null == task.getAssignment());
}
static Set<String> getCapableStations(Maintenance<?> task)
{
Set<String> capableStations = newHashSet();
if(task.getCapStationList() != null)
{
capableStations.addAll(Arrays.asList(task.getCapStationList().split(StringConstants.COMMA_SPLIT_REGEX)));
}
if(task.getCapStationClassList() != null)
{
Map<String, List<String>> stationClassMap = CacheManager.get(STN_CLASS.name());
List<String> stationClass = Arrays.asList(task.getCapStationClassList().split(StringConstants.COMMA_SPLIT_REGEX));
for(String stnClass : stationClass)
{
capableStations.addAll(stationClassMap.get(stnClass));
}
}
return capableStations;
}
}
public static Report calculateInconsitencyReport(Maintenance<?> task) {
Set<InconsistencyReport> enumSet = null;
for(InconsistencyReport iReport : InconsistencyReport.values())
{
if(iReport.findInconsistency(task))
{
if(null==enumSet)
enumSet = EnumSet.of(iReport);
else
enumSet.add(iReport);
}
}
if(null!= enumSet && enumSet.size() > 0)
return Report.buildReport(task,enumSet);
return null;
}
}
Helper Interface:
public interface InconsistencyReportIface {
public boolean findInconsistency(Maintenance<?> task );
public boolean validate(Maintenance<?> task );
}
Details of class logic is teared off because of security.
What is the problem? Just create your object when one of your booleans is true.
if(bool1 || bool2 || bool3) {
item = new Item(str1, str2, str3, str4, bool1, bool2, bool3);
}
From what I understand of your description:
a) you will have some bools that will determine wether you create a certain object or not.
b) you may have to include some more bools into the "check protocol"
c) you have to do this checking in a loop where
i/ you check for the bool variable
ii/ you check if the object had been created previously
I still don't quite get it yet, but.. that looks pretty straight forward to me. Let's say your bools are stored in a boolean array boolean[] bools and your strings in a string array String[] strings (which, btw, I don't know what they are used for). You are saying to check if every bool is true and then create an object based on that result.
boolean[] bools = new boolean[] { ... };
String[] strings = new String[] { ... };
boolean checks = false;
for(int i = 0; i<bools.length && !checks; i++)
checks = bools[i];
//so far we will have processed if any of the bools was false, which was your condition
if(checks)
Object object = new Object(); //create your desired object
I don't understand why you would need to check if the object has been constructed previously, though, so I didn't include it in my suggestion :P
I have a java LinkedList which contains several custom objects of the same type.
LinkedList<myClass> = new LinkedList<myClass>();
Within my objects I have a specific value
class myClass(){
public int id;
}
I want to be able to return the index of the linked list for a match of a specific value, i.e: Find the LinkedList index where the object id = 7
I have looked into using indexof, contains, and containsall, but without any luck (index of always returns -1).
Is this something I can do with a prebuild libary, or am I going to have to extend my own search function for custom objects?
Override the equals method on your myClass class so the LinkedList could find the object:
public class myClass {
private int id; //it should be private, not public
//other attributes...
//getters and setters...
#Override
public void equals(Object o) {
if (o == null) return false;
if (o == this) return true;
if (o instanceof myClass) {
myClass x = (myClass)x;
return x.getId() == this.id;
}
return false;
}
}
Since you're overriding equals, you should also override the hashCode method:
#Override
public int hashCode() {
return this.id;
}
The reason for this is explained in the Object class javadoc:
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
Maybe you shoud simple store your objects in an HashMap<key,value>
you put an object in it as value with a key. If you want to search for an Object you just get it over the key. So for example you take your class and use the objectID as key if its unique.
HashMap<Integer, myClass> list = new HashMap<Integer, myClass>();
list.put(newId, new MyClass(newId)); //just an example!
to find it now you just need one line like this:
list.get(newId);
if the newId does not exsist it return null.
LinkedList compares Object using their equals() method. So if you want two instances of your class to be considered equal when they have the same ID, you must override the equals() method:
#Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o == null) {
return false;
}
if (o.getClass() == this.getClass()) {
return this.id == ((MyClass) o).id;
}
return false;
}
When overriding equals(), hashCode() must also be overridden, because two equals objects MUST have the same hashCode:
#Override
public int hashCode() {
return id;
}
Note that if you don't want two instances to be considered equal when they have the same ID, then you have no choice other than iterating the list and finding the first element which has the same ID as the instance you're looking for. Or you must use another data structure, like a Map<Integer, MyClass> for example.
This can be implemented in terms of List's indexOf() method, all you have to do is override equals() and hashChode() in myClass to specify that the comparisons must be made using the id attribute (here is an explanation of why you need to override both methods). Simply add this methods to myClass:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
myClass other = (myClass) obj;
if (id != other.id)
return false;
return true;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
Now to find the index of an element with id == 7 do something like this:
int idx = myList.indexOf(new myClass(7));
That is, assuming that there exists a constructor in myClass that takes the id as a parameter.
You can do it like this
list.indexOf(new Object() {
#Override
public boolean equals(Object o) {
MyClass mine = (MyClass) o;
return mine.id == yourValue;
}
});