DualHashBidiMap and getKey method - java

I have an issue with the DualHashBidiMap and getKey method.
I'm using Commons Collections 4.1
The containsKey method returns true for specific key insterted, but getKey method returns null for the same key;
Key Class have a SuperClass with equals and hashcode method overrided to match by id property.
Main Class
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
DualHashBidiMap<Observed, Object> map=new DualHashBidiMap<Observed,Object>();
Task t66=new Task();
t66.setId(66);
map.put(t66, "Task66");
Task tFetch=new Task();
tFetch.setId(66);
System.out.println("tFetch present:"+map.containsKey(tFetch));
System.out.println("tFetch Object:"+map.getKey(tFetch));
}
}
this is the output
tFetch present:true
tFetch Object:null
Key Class
public class Task extends Observed{
public void m1(){
System.out.println("Method called !!");
}
}
Key SuperClass
public class Observed extends Observable{
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Override
public boolean equals(Object obj) {
boolean retValue=false;
Observed t=(Observed) obj;
if(t.getId().equals(this.getId())) retValue=true;
return retValue;
}
#Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + (this.getId() != null ? this.getId().hashCode() : 0);
hash = 53 * hash + this.getId();
return hash;
}
}
Tnks to all..

You are trying to get key for a value that doesn't exist in the map. May be you want to do as below
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
DualHashBidiMap<Observed, Object> map=new DualHashBidiMap<Observed,Object>();
Task t66=new Task();
t66.setId(66);
map.put(t66, "Task66");
Task tFetch=new Task();
tFetch.setId(66);
System.out.println("tFetch present:"+map.containsKey(tFetch));
// to get the key related to an object
System.out.println("tFetch Object:"+map.getKey("Task66"));
// to get a value related to a key
System.out.println("tFetch Object:"+map.get(tFetch));
}
}

Related

How can UserDefined class be a key of hashmap if hashCode() & equals() return same value

I am trying to implement HashMap with UserDefined class as Key, i am successfull even when I implement both hashCode() (returns 0 for every object) & equals() (returns false for every object). My Code
public class UserDefinedMapKey {
public static void main(String[] args) {
HashMap<Beck, Integer> hm = new HashMap<Beck, Integer>();
hm.put(new Beck(10,"archit"), 20);
hm.put(new Beck(10,"archit"), 30);
hm.put(new Beck(30,"goel"), 50);
for(Map.Entry<Beck, Integer> m : hm.entrySet()) {
System.out.println(m.getKey() + "===" + m.getValue());
}
}
}`
`
class Beck {
int arc;
String grc;
public Beck(int i, String string) {
// TODO Auto-generated constructor stub
}
public int getArc() {
return arc;
}
public void setArc(int arc) {
this.arc = arc;
}
public String getGrc() {
return grc;
}
public void setGrc(String grc) {
this.grc = grc;
}
#Override
public int hashCode() {
return 0;
}
#Override
public boolean equals(Object b) {
return false;
}
}
output:-
main.java.Interview.Beck#0===20
main.java.Interview.Beck#0===30
main.java.Interview.Beck#0===50
Can anyone let me know the reason how it's working
This is happening because equals is returning false. The equals/hashCode contract is completely broken. There is no assertion that if two objects are the same, they are equal. Two objects can have the same hashcode and still not be equal.
What is occurring is that on the 2nd and 3rd put call, there is a check to see if any objects in the given bucket (defined by hashCode) are the same. They are not because equals returns false, so the new object is added to the same bucket.
You need to properly implement the contract properly for it to work properly.
Baeldung tutorial on equals/hashcode contract.

Enum support and custom logic in setters of realm object class

I'm implementing custom logic in setters and enums in realm object class like this.-
public class SellerProducts extends RealmObject{
public Boolean isValid=true;
public String is_valid="";
public String quantity;
public int quantity_;
public String enumvalue;
public void setIs_valid(String is_valid){
if (is_valid.equals("0")) {
this.isValid = false;
}
this.is_valid=is_valid;
}
public String getIs_valid(){
return this.is_valid;
}
public void setQuantity(String quantity){
this.quantity=quantity;
try {
quantity_ = Integer.parseInt(this.quantity);
} catch (NumberFormatException e) {
e.printStackTrace();
}
if (!this.isValid) {
setEnum(ProductType.IN_ACTIVE);
} else if (this.quantity_ <= 0) {
setEnum(ProductType.OUT_OF_STOCK);
} else {
setEnum(ProductType.ACTIVE);
}
}
public String getQuantity(){
return this.quantity;
}
public enum ProductType {
ACTIVE, IN_ACTIVE, OUT_OF_STOCK
};
public void setEnum(ProductType val) {
this.enumvalue=val.toString().toUpperCase();
}
public ProductType getEnum() {
return ProductType.valueOf(enumvalue);
}
}
when i am calling getEnum from the other fragment class it is returning null exception like this
*java.lang.NullPointerException: name == null
at java.lang.Enum.valueOf(Enum.java:189)
at com.localwizard.realm_db.SellerProducts$ProductType.valueOf(SellerProducts.java:331)
at com.localwizard.realm_db.SellerProducts.getEnum(SellerProducts.java:348)*
I'm new to realm so I don't know where I'm wrong?
Ashish, i think you are not setting the ProductType enum and trying to get it and you geeting the exception. Here is the code which i have tried and it is working fine -
public class OtherFragment {
public static void main(String[] aa)
{
SellerProducts sp = new SellerProducts();
sp.setQuantity("10"); // setting the quantity
System.out.println(sp.getEnum()); // ACTIVE is set as Enum
System.out.println(sp.getQuantity()); // 10
System.out.println(sp.getEnum() == ProductType.ACTIVE); // true
sp.setEnum(ProductType.IN_ACTIVE); // Now IN_ACTIVE is set
System.out.println(sp.getEnum() == ProductType.ACTIVE); // false
}
}
If this is not what you want then please add your peace of code, how you meant to set the quantity and trying to get the enum value.
If it answers your question then please accept the answer.

Sorting with abstract class

I had some difficulties in sorting in decreasing order the elements of the following abstract class and its extensions.
package BankServices;
public abstract class Operation {
public Operation (int date, double value){
}
public abstract double getValue();
public abstract int getDate();
public abstract String toString();
}
package BankServices;
public class Deposit extends Operation {
private int date;
private int value;
public Deposit(int date, double value) {
super(date, value);
// TODO Auto-generated constructor stub
}
#Override
public String toString() {
// TODO Auto-generated method stub
return date + "," + value + "+";
}
#Override
public double getValue() {
// TODO Auto-generated method stub
return value;
}
#Override
public int getDate() {
// TODO Auto-generated method stub
return date;
}
}
package BankServices;
public class Withdrawal extends Operation{
private int date;
private double value;
public Withdrawal(int date, double value) {
super(date, value);
// TODO Auto-generated constructor stub
}
#Override
public String toString() {
// TODO Auto-generated method stub
return date + "," + value + "-";
}
#Override
public double getValue() {
// TODO Auto-generated method stub
return value;
}
#Override
public int getDate() {
// TODO Auto-generated method stub
return date;
}
}
I had to implement these methods of the main class returning sorted lists in descending order:
public List<Operation> getMovements() {
Collections.sort(operations, new Comparator<Operation>(){
public int compare(Operation a, Operation b){
return (int) (b.getDate() - a.getDate());
}
});
return operations;
}
public List<Deposit> getDeposits() {
Collections.sort(deposits, new Comparator<Operation>(){
public int compare(Operation a, Operation b){
return (int) (b.getValue() - a.getValue());
}
});
return deposits;
}
public List<Withdrawal> getWithdrawals() {
Collections.sort(withdrawals, new Comparator<Operation>(){
public int compare (Operation a, Operation b){
return (int) (b.getValue() - a.getValue());
}
});
return withdrawals;
}
the first one returns a List ordered by date, while getDeposits() and getWithdrawals() return List and List ordered by value..
Could you please suggest how to make it work without mistakes and failures?
Thank you very much in advance.
Instead of this - use compareTo(...) method which is both on Double and Date, so for example:
Collections.sort(withdrawals, new Comparator<Operation>(){
public int compare (Operation a, Operation b){
return Double.valueOf(b.getValue()).compareTo(Double.valueOf(a.getValue()));
}
});
Still, your code should work, except for some weird data you can have there... But not for real life data I think
EDIT: I was wrong, your code would only work if difference between doubles would be over 1.

Unique classes in generic list

I have a generic class with a generic list in it. I want to ensure that the generic list only contains unique classes.
What I have done so far is to compare the class names with reflection (getClass()). But I think that's not a clean solution. Are there any better practices to check?
public class MyGenericClass<T extends MyGenericClass.MyInterface> {
private List<T> members = new ArrayList<>(0);
public void add(T t) {
final boolean[] classInMembers = {false};
members.forEach(member -> {
if (member.getClass().getName().equals(t.getClass().getName())) {
classInMembers[0] = true;
}
});
if (!classInMembers[0]) {
members.add(t);
}
}
public interface MyInterface {
void doSomething(String text);
}
}
public class Main {
public static void main(String[] args) {
MyGenericClass<MyGenericClass.MyInterface> myGenericClass = new MyGenericClass<>();
myGenericClass.add(new Performer1());
myGenericClass.add(new Performer2());
myGenericClass.add(new Performer3());
myGenericClass.add(new Performer3()); // should not be inserted!
}
private static class Performer1 implements MyGenericClass.MyInterface {
#Override
public void doSomething(String text) {
text = "Hi, I am performer 1!";
}
}
private static class Performer2 implements MyGenericClass.MyInterface {
#Override
public void doSomething(String text) {
text = "Hi, I am performer 2!";
}
}
private static class Performer3 implements MyGenericClass.MyInterface {
#Override
public void doSomething(String text) {
text = "Hi, I am performer 3!";
}
}
}
You could subclass a java.util.Set interface implementation. It will likely be easiest to subclass java.util.AbstractSet.
By default 'Set' will compare objects by their .equals() method - In your case, this is not sufficient. You will need to override the contains method to ensure that only instances of a unique class are added.
In your overrideen contains, it's probably the same / easier to compare class instances rather than their stringified package name
I.e. use a.getClass() == b.getClass(), rather than a.getClass().getName()
Don't use a List, use a java.util.Set instead.
A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element.
If the iteration order is important or if you want to use a custom Comparator, the TreeSet implementation can be used:
A NavigableSet implementation based on a TreeMap. The elements are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.
Example of a Set using a Comparator:
class MyComparator implements Comparator<Object> {
#Override
public int compare(Object e1, Object e2) {
if (e1.getClass() == e2.getClass())
return 0;
//if you wish to have some extra sort order
return e1.getClass().getName().compareTo(e2.getClass().getName());
}
}
. . .
Set mySet = new TreeSet<Object>(new MyComparator());
mySet.add(new Object());
mySet.add(new Object());//same class already in set
mySet.add("wtf");
//mySet.size() is now 2 - the second "new Object()" was not inserted due to the comparator check
Why so complicated?
public class Main {
public static void main(String[] args) {
final Class<?> helloClass = "Hello".getClass();
final Class<?> worldClass = "World".getClass();
final Class<?> intClass = Integer.class;
System.out.println(helloClass.equals(worldClass)); // -> true
System.out.println(helloClass.equals(intClass)); // -> false
}
}
You could maintain a roster of members in a Set.
public static class MyGenericClass<T extends MyGenericClass.MyInterface> {
private List<T> members = new ArrayList<>(0);
// Add this.
private Set<Class<?>> roster = new HashSet<>();
public void add(T t) {
if (!roster.contains(t.getClass())) {
members.add(t);
roster.add(t.getClass());
}
}
private void soundOff() {
for (T t : members) {
t.doSomething();
}
}
public interface MyInterface {
void doSomething();
}
}
private static class Performer implements MyGenericClass.MyInterface {
final int n;
public Performer(int n) {
this.n = n;
}
#Override
public void doSomething() {
System.out.println("Hi, I am a " + this.getClass().getSimpleName() + "(" + n + ")");
}
}
private static class Performer1 extends Performer {
public Performer1(int n) {
super(n);
}
}
private static class Performer2 extends Performer {
public Performer2(int n) {
super(n);
}
}
private static class Performer3 extends Performer {
public Performer3(int n) {
super(n);
}
}
public void test() {
MyGenericClass<MyGenericClass.MyInterface> myGenericClass = new MyGenericClass<>();
myGenericClass.add(new Performer1(1));
myGenericClass.add(new Performer2(2));
myGenericClass.add(new Performer3(3));
myGenericClass.add(new Performer3(4)); // should not be inserted!
myGenericClass.soundOff();
}
You could implement a Wrapper which provides the necessary comparison and add the wrapped instance to the set. This way you don't have to override equals and hashcode in your concrete Performer classes and you don't have to subclass a concrete Set implementation (which you are coupled to. When you subclass a HashSet, you have to use that concrete class. But what if you want to use a LinkedHashSet at some point? You have to override LinkedHashSet as well) , which may be fragile since you have to make sure that the overridden method is consistent with the rest of the class.
class MyGenericClass<T extends MyInterface> {
private Set<ClassCompareWrapper<T>> members = new HashSet<>();
public void add(T t) {
members.add(new ClassCompareWrapper<T>(t));
}
}
class ClassCompareWrapper<T> {
T t;
public ClassCompareWrapper(T t) {
this.t = t;
}
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof ClassCompareWrapper))
return false;
ClassCompareWrapper<?> that = (ClassCompareWrapper<?>) o;
return Objects.equals(t.getClass(), that.t.getClass());
}
#Override
public int hashCode() {
return Objects.hash(t.getClass());
}
#Override
public String toString() {
return "Wrapper{" +
"t=" + t +
'}';
}
}
Here are a few other ideas.
Using streams:
public void add(T t) {
if (!members.stream().anyMatch(m -> m.getClass() == t.getClass())) {
members.add(t);
}
}
Using AbstractSet and HashMap:
class ClassSet<E> extends AbstractSet<E> {
private final Map<Class<?>, E> map = new HashMap<>();
#Override
public boolean add(E e) {
// this can be
// return map.putIfAbsent(e.getClass(), e) != null;
// in Java 8
Class<?> clazz = e.getClass();
if (map.containsKey(clazz)) {
return false;
} else {
map.put(clazz, e);
return true;
}
}
#Override
public boolean remove(Object o) {
return map.remove(o.getClass()) != null;
}
#Override
public boolean contains(Object o) {
return map.containsKey(o.getClass());
}
#Override
public int size() {
return map.size();
}
#Override
public Iterator<E> iterator() {
return map.values().iterator();
}
}
A HashMap could also be used without wrapping it in a Set. The Set interface is defined around equals and hashCode, so any implementation which deviates from this is technically non-contractual. Additionally, you might want to use LinkedHashMap if the values are iterated often.

Set ordered by "add() count"

I'm trying to implement a Set which is ordered by the count of additions like this:
public class App {
public static void main(String args[]) {
FrequencyOrderedTreeSet<String> set = new FrequencyOrderedTreeSet<String>();
set.add("bar");
set.add("foo");
set.add("foo");
Iterator<String> i = set.iterator();
while (i.hasNext()) {
System.out.print(i.next());
}
// prints "foobar"
}
}
I've created a protected class FrequencyOrderedTreeSet.Element which implements Comparable and has a T entry and an int frequency property and extended TreeSet<FrequencyOrderedTreeSet.Element> with FrequencyOrderedTreeSet<T> and overrode the compareTo and equals methods on the Element.
One problem is that I can't override the add() method because of type erasure problems and also I can't call instanceof Element in the equals method, because in case object given to it is an Element, I have to compare their entries, but if it's not, I have to compare the object itself to this.entry.
In the add method I create a new element, find the element with the same entry in the set, set the frequency on the new element to "old+1", remove the old one and add the new one. I'm not even sure this is the best way to do this or if it would work even because the other problems I described.
The question is: what's the best way to implement such data structure? In case I'm somehow on the right track - how can I circumvent the problems I've mentioned above?
Here's a basic implementation. It's not the most optimal and will take some more work if you want to implement the full Set interface.
public class FrequencySet<T> implements Iterable<T>
{
private TreeSet<T> set;
private HashMap<T, Integer> elements = new HashMap<T, Integer>();
public FrequencySet()
{
set = new TreeSet<T>(new Comparator<T>()
{
public int compare(T o1, T o2)
{
return elements.get(o2)-elements.get(o1);
}
});
}
public void add(T t)
{
Integer i = elements.get(t);
elements.put(t, i == null ? 1 : i+1);
set.remove(t);
set.add(t);
}
public Iterator<T> iterator() {return set.iterator();}
public static void main(String [] args)
{
FrequencySet<String> fset = new FrequencySet<String>();
fset.add("foo");
fset.add("bar");
fset.add("foo");
for (String s : fset)
System.out.print(s);
System.out.println();
fset.add("bar");
fset.add("bar");
for (String s : fset)
System.out.print(s);
}
}
The key is in the add method. We change the counter for the given object (which changes the relation order), remove it from the backing set and put it back in.
This works the other way (count is increased when you use GET)
#SuppressWarnings("rawtypes")
final class Cache implements Comparable {
private String key;
private String value;
private int counter;
public String getValue() {
counter++;
return value;
}
private void setValue(String value) { this.value = value; }
public String getKey() { return key; }
private void setKey(String key) { this.key = key; }
public int getCounter() { return counter; }
public void setCounter(int counter) { this.counter = counter; }
public Cache(String key, String value) {
this.setKey(key);
this.setValue(value);
setCounter(0);
}
#Override
public int compareTo(Object arg0) {
if(!(arg0 instanceof Cache)) {
throw new ClassCastException();
}
return this.getCounter() - ((Cache) arg0).getCounter();
}
}

Categories