Ok, so I've got a method which adds elements to a list but it is always throwing my custom exception, no matter what, even when there are no elements in the Set I made.
private Set<Plan> planSet = new HashSet<Plan>();
public Plan createPlan(String name) throws DuplicatePlan{
Plan plan = new Plan(name);
if(!planSet.contains(plan)){
planSet.add(plan);
} else {
throw(new DuplicatePlan("Error, duplicate plan"));
}
return plan;
}
I'm thinking that my equals() and hashCode() methods are causing this. Currently I'm using the default overridden Eclipse hashCode() and equals(), this is what I've got there:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
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;
}
Plan other = (Plan) obj;
if (name == null) {
if (other.name != null){
return false;
}
} else if (!name.equals(other.name)){
return false;
}
return true;
}
This is what Plan does:
private String name;
private Set<Tables> tablesSet;
public Plan(String name){
this.name = name ;
}
Here's what's supposed to happen if a user sets the same name in the TextField:
newPlan.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent action){
if(!newPlan.getText().isEmpty()){
try {
String name = planName.getText();
plan.createPLan(name);
esquema = esquemas.createPlan(planName.getText());
optionsPlans.getItems().add(plan.getName());
} catch (DuplicatePlan e) {
dialog.errorDialog(planError, duplicate);
}
} else {
dialog.errorDialog(empty, emptySpace);
}
}
});
Had to use Answer because it was too long for comment.
This here looks suspicious to me:
String name = planName.getText();
plan.createPLan(name);
esquema = esquemas.createPlan(planName.getText());
I.e. what's up with createPLan and createPlan? Copy & paste error? Or are you calling the same method twice (which would explain the behavior)?
Related
My intention was to make a caching service for a database results, that I can paginate differently based on client's requests.
So, upon the (search) request I am making a key that is composed of parameters, which are in form of two Map<String, String[]> and a:
public class DocMaintainer {
public Manipulator creator;
public Manipulator lastChange;
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DocMaintainer that = (DocMaintainer) o;
return Objects.equals(creator, that.creator) &&
Objects.equals(lastChange, that.lastChange);
}
#Override
public int hashCode() {
return Objects.hash(creator, lastChange);
}
}
public class Manipulator {
public Date fromDate;
public Date toDate;
public String userId;
public String system;
public Manipulator() {
this.userId = "";
this.system = "";
this._fromJoda = new DateTime(Long.MIN_VALUE);
this._toJoda = new DateTime(Long.MAX_VALUE - DateTimeConstants.MILLIS_PER_WEEK);
}
private DateTime _fromJoda;
private DateTime _toJoda;
public DateTime get_fromJoda() {
_fromJoda = fromDate != null ? new DateTime(fromDate) : _fromJoda;
return _fromJoda;
}
public DateTime get_toJoda() {
_toJoda = toDate != null ? new DateTime(toDate) : _toJoda;
try {
_toJoda = _toJoda.plusDays(1);
} catch (Exception e) {
System.out.println(e);
}
return _toJoda;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Manipulator that = (Manipulator) o;
return Objects.equals(fromDate, that.fromDate) &&
Objects.equals(toDate, that.toDate) &&
Objects.equals(userId, that.userId) &&
Objects.equals(system, that.system);
}
#Override
public int hashCode() {
return Objects.hash(fromDate, toDate, userId, system);
}
}
As you can see I intended to use hashing to create a "key":
public class SearchKey {
public int conjunctionHash;
public int disjunctionHash;
public int maintainerHash;
public SearchKey(int conjunctionHash, int disjunctionHash, int maintainerHash) {
this.conjunctionHash = conjunctionHash;
this.disjunctionHash = disjunctionHash;
this.maintainerHash = maintainerHash;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SearchKey searchKey = (SearchKey) o;
return conjunctionHash == searchKey.conjunctionHash &&
disjunctionHash == searchKey.disjunctionHash &&
maintainerHash == searchKey.maintainerHash;
}
#Override
public int hashCode() {
return Objects.hash(conjunctionHash, disjunctionHash, maintainerHash);
}
}
a key-object is used directly as a caching key in a singleton service:
#Named
#Singleton
public class SearchCacheSrv {
private Map<SearchKey, ValidMainteinersList<FindDTO>> cache = new HashMap<>();
public ValidMainteinersList<FindDTO> getCached(SearchKey searchKey) {
if (cache.containsKey(searchKey))
return cache.get(searchKey);
else
return new ValidMainteinersList<FindDTO>();
}
public SearchKey makeAkey(Map<String, String[]> conjunction,
Map<String, String[]> disjunction,
DocMaintainer maintainer) {
return new SearchKey(conjunction.hashCode(), disjunction.hashCode(), maintainer.hashCode());
}
public ValidMainteinersList<FindDTO> cache(SearchKey searchKey, ValidMainteinersList<FindDTO> findDTOS) {
return cache.put(searchKey, findDTOS);
}
public void clearCache() {
cache.clear();
}
}
Unfortunately this is not behaving the way I expected and I'm getting different hashes/keys generated for the same parameters.
Naturally question is why?
The problem here is that the hashCode of an array does not depend on the contents, but on the reference. That means that if you have two conjunction / disjunction keys that are equal, but the contained arrays are not the same objects, then the hashcode of the keys will be different.
The solution that probably takes the least effort is replacing the arrays with ArrayLists, which do base their hashCode on the content.
I actually don't see the point of passing conjunction.hashCode(), ... to your SearchKey constructor; I never had to do it this way, but it could be my mistake.
Try passing actual values to your SearchKey class, not hashCodes, so the hashCode method always returns a consistent value.
Class:
public class Variant
{
private String variant;
private String quantity;
//getters and setters
}
ArrayList:
ArrayList<Variant> variantList = getVariantsList();
Now I want to check whether variantList contains a duplicate entry of variant or not? Please note that variant having two entries with different quantity are to be considered as duplicates.
You can simply ovveride your equals method in your Variant class and provide all the rules for equality in that method.
#Override
public boolean equals(Object obj) {
..
Then you can use contains method or just pass it to a Set, that eliminates all your duplicates.
If you want variant having two entries with different quantity also considered as dup, then you can add that condition in your equals.
Override equals(Object obj) method and try to compare the object on variant and quantity.
Try to loop thru the variantList and do check for duplicity using variantList.contains(variant).
There are two things you need to do:
Override the equals() in your Variant class(minimal code below):
Please note that the below code only checks for quantity and not the variant prop. Your IDE might help you to generate the equals() as well.
#Override
public boolean equals(Object object) {
boolean isEqual = (this == object);
if(object instanceof Variant){
Variant variant = (Variant) object;
isEqual = this.quantity.equals(variant.quantity);
}else{
isEqual = false;
}
return isEqual;
}
Check if the List contains the object - which will use the equals() to check if both are equal.
for (Variant variant : variantList) {
if (variantList.contains(variant)) {
//do logic if its present
}
}
Just check one object with other objects of list
Override equals method in Variant class
#Override
public boolean equals(Object obj) {
if (obj != null) {
if (obj instanceof Variant) {
Variant temp = (Variant) obj;
return this.quantity.equals(temp.quantity); //for different quantity
} else {
return false;
}
}
return false;
}
Then check :
for (int i = 0; i < variantList.size(); i++) {
for (int j = 0; j < variantList.size(); j++) {
if (i != j) {
if (iList.get(i).equals(iList.get(j))) {
//logic when duplicate
break;
}
}
}
}
Follow the below guidelines:
Your Class Variant must override the equals method, since you define a duplicate condition based on quality hence in the equals method check for quality attribute value i.e.
public class Variant {
private String variant;
private String quantity;
public Variant(String variant, String quantity) {
this.variant = variant;
this.quantity = quantity;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((quantity == null) ? 0 : quantity.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;
Variant other = (Variant) obj;
if (quantity == null) {
if (other.quantity != null)
return false;
} else if (!quantity.equals(other.quantity))
return false;
return true;
}
}
Create a method which basically checking whether your list contains the duplicate entries(Variant) or not and return true and false accordingly:
private static boolean isListContainsDuplicateEntries(
ArrayList variantList) {
final List setToReturn = new ArrayList();
for (Variant v : variantList) {
if (!setToReturn.contains(v)) {
setToReturn.add(v);
} else {
return true;
}
}
return false;
}
Now, test the functionality:
public static void main(String[] args) {
Variant variant1 = new Variant("1", "100");
Variant variant2 = new Variant("2", "200");
Variant variant3 = new Variant("3", "200");
ArrayList<Variant> variantList = new ArrayList<>();
variantList.add(variant1);
variantList.add(variant2);
variantList.add(variant3);
System.out.println(Variant.isListContainsDuplicateEntries(variantList));
Output: true
You can use contains():
if (variantList.contains(**<some other Variant object>**)){
...
}
You can simply override your equals method in your Variant and try like this
List<Varient> list =getVariantsList();
System.out.println("here list size"+list.size());
Set<Varient> set = new HashSet<Varient>(list);
System.out.println("here"+set.size());
Create a varient Object:
public class Varient {
private String variant;
private String quantity;
public String getVariant() {
return variant;
}
public void setVariant(String variant) {
this.variant = variant;
}
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Varient)) return false;
Varient varient = (Varient) o;
if (!quantity.equals(varient.quantity)) return false;
if (!variant.equals(varient.variant)) return false;
return true;
}
#Override
public int hashCode() {
int result = variant.hashCode();
result = 31 * result + quantity.hashCode();
return result;
}
}
Here is your main Program;
public class Test {
public static void main (String [] args){
// getVariantsList() here your list
List<Varient> list =getVariantsList();
Set<Varient> set = new LinkedHashSet<Varient>(list);
}
}
public class Variant {
private String variant;
private String quantity;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((variant == null) ? 0 : variant.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;
Variant other = (Variant) obj;
if (variant == null) {
if (other.variant != null)
return false;
} else if (!variant.equals(other.variant))
return false;
return true;
}
public String getVariant() {
return variant;
}
public void setVariant(String variant) {
this.variant = variant;
}
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
public static void main(String[] args) {
// HashSet<Variant> set = new HashSet<>();
// LinkedHashSet<Variant> linkedSet = new LinkedHashSet<>(); // stores
// in input order
/*
* You can use treeset to store data in custom order, in this case
* lexicographically
*/
TreeSet<Variant> treeSet = new TreeSet<>(new VariantComparator());
}
}
I have a program that I have to use a HashSet for. My question arises from the fact that HashSets mainly contain one object, but if I wish to send information to the other class, it takes three objects: one string, one int, and one boolean.
The assignment says that I must use a HashSet
Constructor I am trying to send information to:
public Magic (String name, int size, boolean isVisible)
I have a class that is supposed to be sending sets of spells containing name, size, and isVisible.
Magic.go() class:
public void go()
{
int i = 0;
while (i < size) {
if (isVisible == true) {
System.out.println(name + "!");
}
i++;
}
}
Just create an object which contains all the three fields like this:
import java.util.Objects;
public class NameSizeVisible {
private final String name;
private final int size;
private final boolean isVisible;
public NameSizeVisible(String name, int size, boolean isVisible) {
this.name = name;
this.size = size;
this.isVisible = isVisible;
}
public String getName() {
return name;
}
public int getSize() {
return size;
}
public boolean isVisible() {
return isVisible;
}
#Override
public int hashCode() {
return Objects.hash(name,size,isVisible);
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
NameSizeVisible other = (NameSizeVisible) obj;
if (isVisible != other.isVisible)
return false;
if (!Objects.equals(name, other.name))
return false;
if (size != other.size)
return false;
return true;
}
}
You can use a HashSet that stores Objects. So you would have:
HashSet<Object> set = new HashSet<>();
set.add(name);
set.add(size);
set.add(isVisible);
Then when you access the objects you just need to cast them to their respective types:
String name = "";
int size = 0;
boolean isVisible = false;
for (Object o : set) {
if (o instanceof String) {
name = (String) o;
} else if (o instanceof int) {
size = (int) o;
} else {
isVisible = (boolean) o;
}
}
Can anyone let me know what goes wrong in this piece of code? I'm pulling my hair out!
There isn't any problem if I use HashMap instead of ConcurrentHashMap. The code is compiled with JDK 5.0
public class MapTest {
public Map<DummyKey, DummyValue> testMap = new ConcurrentHashMap<DummyKey, DummyValue>();
public MapTest() {
DummyKey k1 = new DummyKey("A");
DummyValue v1 = new DummyValue("1");
DummyKey k2 = new DummyKey("B");
DummyValue v2 = new DummyValue("2");
testMap.put(k1, v1);
testMap.put(k2, v2);
}
public void printMap() {
for(DummyKey key : testMap.keySet()){
System.out.println(key.getKeyName());
DummyValue val = testMap.get(key);
System.out.println(val.getValue());
}
}
public static void main(String[] args){
MapTest main = new MapTest();
main.printMap();
}
private static class DummyKey {
private String keyName = "";
public DummyKey(String keyName){
this.keyName = keyName;
}
public String getKeyName() {
return keyName;
}
#Override
public int hashCode() {
return keyName.hashCode();
}
#Override
public boolean equals(Object o) {
return keyName.equals(o);
}
}
private static class DummyValue {
private String value = "";
public DummyValue(String value){
this.value = value;
}
public String getValue() {
return value;
}
}
}
This is the output:
B
Exception in thread "main" java.lang.NullPointerException
at test.MapTest.printMap(MapTest.java:27)
at test.MapTest.main(MapTest.java:34)
DummyKey.equals method implementation is incorrect, due to that testMap.get(key) always returns null. Try this
public boolean equals(Object o) {
if (o instanceof DummyKey) {
DummyKey other = (DummyKey) o;
return keyName == null ? other.keyName == null : keyName.equals(other.keyName);
}
return false;
}
hashCode also needs a little change to be consistent with equals
public int hashCode() {
return keyName == null ? 0 : keyName.hashCode();
}
The problem comes from your equals in DummyKey.
When you call DummyValue val = testMap.get(key);, the hashcode function finds a match (both keyname of k1 and key are the same and so are their hashcode). Yet equals returns false because k1.keyname is equal to "A" which is not equal to key itself, which is actually of type DummyValue: you are not comparing properly!
Therefore, you need to modify your equals function:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DummyKey other = (DummyKey) obj;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
return true;
}
Please note that if you change hashCode(), then you must change equals() as well. Otherwise, you will run into problems. If equals() returns true for two items, then their hashCode() value must be equal! The opposite is not required but preferable for better hashing performance. Here is an implementation of equals() and hashCode().
HINT: if you are using eclipse, you can utilize its source generation capability to create the correct hashCode() and equals() method for you. The only thing you need to do is to pick the instance variables that identify the object. To do so in eclipse, while your source code is open, go to the tabs in the top and choose "source", then choose "Generate hashCode() and equals()..."
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((keyName == null) ? 0 : keyName.hashCode());
return result;
}
Override
public boolean equals(Object other) {
if(this == other) return true; //for optimization
if(! other instanceof this) return false; //also covers for when other == null
return this.keyName == null ? other.keyName == null : this.keyName.equals(other.keyName);
}
As others have pointed, the problem lies in the way you override hashcode and equals.
Two options : 1) Just remove the hashcode and equals and it works fine
2) I let eclipse generate the source for hashcode and equals and it works fine. This is what my eclipse belted out for me :
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((keyName == null) ? 0 : keyName.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;
DummyKey other = (DummyKey) obj;
if (keyName == null) {
if (other.keyName != null)
return false;
} else if (!keyName.equals(other.keyName))
return false;
return true;
}
I have an exam and this was in the mock and im not quite sure how to go about it, this isn't homework its simply trying to understand how to do it. Thanks.
public class Book{
private final String title;
private final String author;
private final int edition;
private Book(String title, String author, int edition)
{
this.title = title;
this.author = author;
this.edition = edition;
}
public String getTitle()
{
return title;
}
public String getAuthor()
{
return author;
}
public String getEdition()
{
return edition;
}
}
I need to provide implementations of equals, hashCode and compareTo methods for the above code.
I'm not to sure how to go about it, would it be somthing similar to this for the compareTo method?
title.compareTo(title);
author.compareTo(author);
edition.compareTo(edition);
Thanks, any help would be greatly appreciated.
your compareTo should be this:
title.compareToIgnoreCase(otherTitle);
...
equals:
if(null == title || null == author || null == editor)
{
return false;
}
if(!title.equals(otherTitle)
{
return false;
}
if(!author.equals(otherAuthor)
{
return false;
}
if(!editor.equals(otherEditor)
{
return false;
}
return true;
Take look at this.
http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/builder/package-summary.html
You can use the builders in this package to create default implementations.
IDEs like Eclipse can generate hashCode and equals methods for you (Source -> generate hashCode() and equals()). You can even specify which fields of the object need to match for it to be considered "equal".
For instance here is what Eclipse generates for your class:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((author == null) ? 0 : author.hashCode());
result = prime * result + edition;
result = prime * result + ((title == null) ? 0 : title.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;
Book other = (Book) obj;
if (author == null) {
if (other.author != null)
return false;
} else if (!author.equals(other.author))
return false;
if (edition != other.edition)
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}