How to implement equals method which works on generics - java

I have the following problem. I have the following classes
public class Main {
public static void main(String[] args) {
// Expected: true
// Results in: true
List<String> strLst = new ArrayList<>();
strLst.add(new String("A"));
System.out.println(strLst.contains(new String("A")));
// Expected: true
// Results in: true
List<Number> numLst = new ArrayList<>();
numLst.add(new Number(1));
System.out.println(numLst.contains(new Number(1)));
// Expected: true
// Results in: false
Container<String> integers = new Container<>();
integers.add(new String("A"));
System.out.println(integers.contains(new String("A")));
// Expected: true
// Results in: false
Container<Number> numbers = new Container<>();
numbers.add(new Number(1));
System.out.println(numbers.contains(new Number(1)));
}
}
class Container<T> {
ArrayList<Node<T>> internal = new ArrayList<>();
public void add(T elem) {
internal.add(new Node<>(elem));
}
public boolean contains(T label) {
for (Node<T> e : internal) {
if (e.getLabel().equals(e)) {
return true;
}
}
return false;
}
}
class Node<T> {
T label;
public Node(T label) {
this.label = label;
}
public T getLabel() {
return label;
}
}
class Number {
private int val;
public Number(int val) {
this.val = val;
}
public boolean equals(Object o) {
if (o instanceof Number) {
return this.val == ((Number) o).val;
}
return false;
}
}
I am not sure what went wrong here. I would expect similar behavior with my Container as with ArrayList. But it does not, because in my opinion ArrayList (see https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/ArrayList.java#L251) implements contains in a similar way.
What does ArrayList do different than I do? And if it is not possible to implement such behavior the way I hope to, how would I do this alternatively?

The line
if (e.getLabel().equals(e)) {
in contains should be
if (e.getLabel().equals(label)) {
Solution:
public boolean contains(T label) {
for (Node<T> e : internal) {
if (e.getLabel().equals(label)) {
return true;
}
}
return false;
}

Related

Java HashSet doesn't add two objets with same hashCode and equals (OK) but contains() says second object is not in set

I have a test for testing that adding the same Edge (Arista) but with the same vertices (but flipped order) is the same (this is not a directed graph).
And this is strange because the two first assertions passes OK (adding Edge1 and Edge2 will result in edges.sizes = 1 because they are the same, theoretically).
But then when testing that edges.contains(Edge2) returns false.
Why could it have worked when testing addition (to not add it duplicated) but does not work when testing contains()?
This is the code:
#Test
public final void testAristaWithSameVerticesIsNotAddedTwice() throws Exception {
Grafo grafo = new Grafo();
Vertice vertice1 = new Vertice("Vertice 1");
Vertice vertice2 = new Vertice("Vertice 2");
grafo.agregarVertice(vertice1);
grafo.agregarVertice(vertice2);
Arista arista = new Arista(vertice1, vertice2, 10);
Arista arista2 = new Arista(vertice2, vertice1, 10);
grafo.agregarArista(arista);
grafo.agregarArista(arista);
assertEquals(1, grafo.getAristasQuantity());
assertTrue(grafo.hasArista(arista));
assertTrue(grafo.hasArista(arista2)); // fails here
}
Grafo class:
private HashSet<Arista> aristas;
public boolean hasArista(Arista arista) {
return this.aristas.contains(arista);
}
Arista class
package entities;
public class Arista {
protected Vertice vertice1;
protected Vertice vertice2;
protected int peso;
public Arista(Vertice vertice1, Vertice vertice2, int peso) {
this.vertice1 = vertice1;
this.vertice2 = vertice2;
this.peso = peso;
}
public Vertice getVertice1() {
return vertice1;
}
public Vertice getVertice2() {
return vertice2;
}
public int getPeso() {
return peso;
}
public void setPeso(int peso ) {
this.peso = peso;
}
public int hashCode() {
return vertice1.hashCode() + vertice2.hashCode();
}
public boolean equals(Arista arista) {
if (arista == this) {
return true;
}
if ((arista.getVertice1() == this.vertice1 && arista.getVertice2() == this.vertice2)
|| (arista.getVertice2() == this.vertice1 && arista.getVertice1() == this.vertice2)) {
return true;
}
return false;
}
}
I found out that the equals() wasn't overriding the parent definition because it was not well defined. So it wasn't being called.
Correct way is:
#Override
public boolean equals(Object object) {
if (object instanceof Arista) {
Arista arista = (Arista) object;
if (arista == this) {
return true;
}
if ((arista.getVertice1() == this.vertice1 && arista.getVertice2() == this.vertice2)
|| (arista.getVertice2() == this.vertice1 && arista.getVertice1() == this.vertice2)) {
return true;
}
}
return false;
}

Make function generic for List<Boolean> and boolean[]

I have two functions which check if all elements of an array or list are true. I'm having trouble combining the two. How can I make the functions into one generic Java function.
public static boolean allTrue(boolean[] booleans) {
if (booleans == null) {
return false;
}
for (boolean bool : booleans) {
if (!bool) {
return false;
}
}
return true;
}
public static boolean allTrue(List<Boolean> booleans) {
if (booleans == null) {
return false;
}
for (boolean bool : booleans) {
if (!bool) {
return false;
}
}
return true;
}
If you're using Guava, you can wrap the boolean array in Booleans.asList() and pass it as a list:
public static boolean allTrue(boolean[] booleans) {
return booleans != null && allTrue(Booleans.asList(booleans));
}
As per https://stackoverflow.com/a/5606435/2310289
You could just accept an Object
public static boolean allTrue(Object booleans) {
and then check for instanceof boolean[] or instanceof List<Boolean> and then perform different code within the method.
Again, not really an improvement, but a bit closer to code unification
I think the answer given by #Joel was a good one, except for the issue pointed out in the comment. If we just convert boolean[] to Boolean[], we can try the following:
public static boolean allTrue(List<Boolean> booleans) {
if (booleans == null) {
return false;
}
for (boolean bool : booleans) {
if (!bool) {
return false;
}
}
return true;
}
public static boolean allTrue(boolean[] booleans) {
Boolean[] newArray = new Boolean[booleans.length];
int i = 0;
for (boolean value : booleans) {
newArray[i++] = Boolean.valueOf(value);
}
return Arrays.asList(newArray);
}
The common ancestor for List<Boolean> and boolean[] is Object, so unless you are okay with allTrue(Object booleans), you cannot do it with one method.
If you change your method signature to allTrue(Iterable<Boolean> booleans), all you have to do is create a special Iterator<Boolean> to traverse the boolean array.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class BooleanAllTrue {
public static boolean allTrue(Iterable<Boolean> booleans) {
if (booleans == null) return false;
for (Boolean bool : booleans) {
if (!bool) return false;
}
return true;
}
public static Iterable<Boolean> asIterable(final boolean[] booleens) {
return new Iterable<Boolean>() {
public Iterator<Boolean> iterator() {
final boolean[] booleans = booleens;
return new Iterator<Boolean>() {
private int i = 0;
public boolean hasNext() {
return i < booleans.length;
}
public Boolean next() {
if (!hasNext()) throw new NoSuchElementException();
return booleans[i++];
}
public void remove() {throw new UnsupportedOperationException("remove");}
};
}
};
}
public static void main(String [] args) {
System.out.println(allTrue(asIterable(new boolean[]{true, true})));
System.out.println(allTrue(asIterable(new boolean[]{true, false})));
try {
asIterable(new boolean[0]).iterator().next();
} catch (NoSuchElementException e) {
// expected
}
}
}
And finally the allTrue(boolean[] booleans) method.
public static boolean allTrue(boolean[] booleans) {
return allTrue(asIterable(booleans));
}

Treeview in Nattable

I'm looking for a way to create a treeTable view in Nattable. I already have a NatTable implemented with filter, sorting, ...
But now I'm looking into a TreeTable like the TreeGridWithCheckBoxFieldsExample from the Nattable examples. The only requirement is that I do not change my datamodel for the tree.
I have two different objects Company and role. Every company does has all the roles. So in this situation I need a tree with all the companies as root object and all the roles beneath all the companies.
From the example it looks like I need to create a format class that implements the TreeList.Format but they are using the model to link the parent (I will not do this because it's a violation of the MVC principle.
Can someone get me on track to create a treetable view in NatTable?
After checking some example of Natable I got a working treeTable. But have only one problem left. The parent items are not correctly shown.
The treeFormat looks like:
public class TreeFormat implements TreeList.Format<PermissionViewModel> {
public TreeFormat() {
}
#Override
public Comparator getComparator(int depth) {
return new Comparator<PermissionViewModel>() {
#Override
public int compare(PermissionViewModel object1, PermissionViewModel object2) {
return object1.getModuleName().compareTo(object2.getModuleName());
}
};
}
#Override
public void getPath(List<PermissionViewModel> path, PermissionViewModel element) {
path.add(element);
PermissionViewModel parent = element.getParent();
while (parent != null) {
path.add(parent);
parent = parent.getParent();
}
Collections.reverse(path);
}
#Override
public boolean allowsChildren(PermissionViewModel element) {
return true;
}
The model that I use is a viewModel and is a one to one map to the normal model
public class PermissionViewModel implements Comparable {
private PermissionViewModel parent;
private ArrayList<PermissionViewModel> children = new ArrayList();
private Integer permissionId;
private String moduleName;
private String permissionName;
private boolean active;
private boolean on;
public PermissionViewModel(PermissionViewModel parent, Permission permission) {
this.parent = parent;
if (parent != null) {
parent.addChild(this);
}
if(parent == null && permission != null)
{
this.permissionId = 0;
this.moduleName = "";
this.permissionName = permission.getModuleName();
this.active = false;
}
else
{
this.permissionId = permission.getPermissionId();
this.moduleName = permission.getModuleName();
this.permissionName = permission.getPermissionName();
this.active = permission.isActive();
}
}
public PermissionViewModel getParent() {
return this.parent;
}
public void addChild(PermissionViewModel child) {
this.children.add(child);
}
public List getChildren() {
return this.children;
}
public PermissionViewModel getSelf() {
return this;
}
public boolean isOn() {
if (this.children.size() == 0) {
return this.on;
} else {
return getCheckBoxState() == CheckBoxStateEnum.CHECKED;
}
}
public void setOn(boolean on) {
if (this.children.size() == 0) {
this.on = on;
} else {
for (PermissionViewModel child : this.children) {
child.setOn(on);
}
}
}
public CheckBoxStateEnum getCheckBoxState() {
if (this.children.size() == 0) {
return this.on ? CheckBoxStateEnum.CHECKED
: CheckBoxStateEnum.UNCHECKED;
} else {
boolean atLeastOneChildChecked = false;
boolean atLeastOneChildUnchecked = false;
for (PermissionViewModel child : this.children) {
CheckBoxStateEnum childCheckBoxState = child.getCheckBoxState();
switch (childCheckBoxState) {
case CHECKED:
atLeastOneChildChecked = true;
break;
case SEMICHECKED:
return CheckBoxStateEnum.SEMICHECKED;
case UNCHECKED:
atLeastOneChildUnchecked = true;
break;
}
}
if (atLeastOneChildChecked) {
if (atLeastOneChildUnchecked) {
return CheckBoxStateEnum.SEMICHECKED;
} else {
return CheckBoxStateEnum.CHECKED;
}
} else {
return CheckBoxStateEnum.UNCHECKED;
}
}
}
#Override
public int compareTo(Object o) {
return 0;
}
public Integer getPermissionId() {
return permissionId;
}
public String getModuleName() {
return moduleName;
}
public String getPermissionName() {
return permissionName;
}
public boolean isActive() {
return active;
}
}
Putting data in the tree table will be done with following source:
ArrayList<PermissionViewModel> permissionViewModelsList = new ArrayList<>();
String previousModule = "";
PermissionViewModel currentParent = null;
for (Permission element : repo.getAllData()) {
if(!previousModule.equals(element.getModuleName()))
{
previousModule = element.getModuleName();
currentParent = new PermissionViewModel(null, element);
permissionViewModelsList.add(currentParent);
permissionViewModelsList.add(new PermissionViewModel(currentParent, element));
}
else
{
permissionViewModelsList.add(new PermissionViewModel(currentParent, element));
}
}
Collections.reverse(permissionViewModelsList);
permissionTable.setItems(permissionViewModelsList);
permissionTable.refresh(true);
But when I look at the table the root elements are viewed but the childeren of the root elements are wrong. I viewed the list of elements and there I can't find any issues. Can someone find the issue that I have?
I changed to order of the columns. I placed the "Module Name" before the "Name" column. And the parent module name has been placed in the module name column. This fixed my problem.
The issue in this case was that the comperator that I used is not working on mixed data in the same fields. Tnx to Dirk Fauth I found it.

Inexplicable Issue with Add Method of a Simple Binary Tree

My binary tree looks pretty close to my class materials, but when I print to the console or check for contains(), any adds I'm doing aren't registered.
I don't have a great understanding of static and the debugger is giving me a hint about making a static reference to non-static variable overallRoot, but everything compiles without error or warning in eclipse.
public class BSTSimpleSet<E extends Comparable<E>> implements SimpleSet<E> {
private GTNode<E> overallRoot;
private int size;
public static void main(String[] args) {
BSTSimpleSet<Integer> main = new BSTSimpleSet<Integer>(2);
main.toString();
main.add(3);
main.toString();
main.add(4);
main.toString();
main.add(5);
main.toString();
System.out.print(main.contains(3));
}
public BSTSimpleSet() {
size = 0;
}
public BSTSimpleSet(E input) {
overallRoot = new GTNode<E>(input);
size = 1;
}
public boolean add(E e) {
return add(e, overallRoot);
}
private boolean add(E e, GTNode<E> root) {
if (root == null) {
root = new GTNode<E>(e);
size++;
return true;
} else {
int compare = e.compareTo(root.data);
if (compare == 0) {
return false;
} else if (compare < 0) {
return add(e, root.left);
} else {
return add(e, root.right);
}
}
}
public void clear() {
overallRoot = null;
}
public boolean contains(E e) {
return contains(e, overallRoot);
}
private boolean contains(E e, GTNode<E> root) {
if (root == null) {
return false;
} else {
int compare = e.compareTo(root.data);
if (compare == 0) {
return true;
} else if (compare < 0) {
return contains(e, root.left);
} else {
return contains(e, root.right);
}
}
}
public boolean isEmpty() {
if (overallRoot == null) {
return false;
} else {
return true;
}
}
public int size() {
return size;
}
public String toString() {
this.toString(overallRoot, 0);
return null;
}
private void toString(GTNode<E> root, int level) {
if (root != null) {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
System.out.println(root.data);
toString(root.left, level + 1);
toString(root.right, level + 1);
} else {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
System.out.println("_");
}
}
private static class GTNode<E extends Comparable<E>> {
public E data;
public GTNode<E> left;
public GTNode<E> right;
public GTNode(E input) {
this(input, null, null);
}
public GTNode(E input, GTNode<E> lNode, GTNode<E> rNode) {
data = input;
left = lNode;
right = rNode;
}
}
}
This code does absolutely nothing.
private boolean add(E e, GTNode<E> root) {
if (root == null) {
root = new GTNode<E>(e);
size++;
return true;
}
...
Java passes in the Object Reference to a method. If you change the Reference, that will not
be propagated back to the calling method. If you change what the Reference refers to
that will be propagated back.
eg
// arrays behave the same way so using them to illustrate.
public void callMethods(){
int[] array = new int[1];
array[0] = 0;
doesNotChange(array);
System.out.println(array[0]);// will print 0
doesAChange(array);
System.out.println(array[0]);// will print 1
}
public void doesNotChange(int[] myArray){
myArray = new int[1];
myArray[0] = 1;
}
public void doesAChange(int[] myArray){
myArray[0] = 1;
}
To avoid these sorts of things I recommend always setting method parameters final.
The GTNode class shouldn't be static. Static classes are classes with only static methods, which means they don't have to be instantiated. The prototypical example of this is the java.lang.Math class: You don't need to call something like Math m = new Math(); m.cos(); to get the cosine, you just call Math.cos(). Since you're creating multiple instances of the GTNode class, make it non-static and you should be good.

Problems with add/remove/equals/string-method in MultiSet-class

This is my class:
public class MultiSet<E> extends AbstractCollection<E>
{
private int size = 0;
private Map<E, Integer> values = new HashMap<E, Integer>();
public MultiSet()
{
}
public MultiSet(Collection<E> c)
{
addAll(c);
}
#Override
public boolean add(E o)
{
throw new UnsupportedOperationException();
}
#Override
public boolean remove(Object o)
{
throw new UnsupportedOperationException();
}
public Iterator<E> iterator()
{
return new Iterator<E>()
{
private Iterator<E> iterator = values.keySet().iterator();
private int remaining = 0;
private E current = null;
public boolean hasNext()
{
return remaining > 0 || iterator.hasNext();
}
public E next()
{
if (remaining == 0)
{
remaining = values.get(current);
}
remaining--;
return current;
}
public void remove()
{
throw new UnsupportedOperationException();
}
};
}
public boolean equals(Object object)
{
if (this == object) return true;
if (this == null) return false;
if (this.getClass() != object.getClass()) return false;
MultiSet<E> o = (MultiSet<E>) object;
return o.values.equals(values);
}
public int hashCode()
{
return values.hashCode()*163 + new Integer(size).hashCode()*389;
}
public String toString()
{
String res = "";
for (E e : values.keySet());
//res = ???;
return getClass().getName() + res;
}
public int size()
{
return size;
}
}
So basically, i need to implement my add/remove-methods correctly, to add or remove elements to/from the Set.
To me, it seems like my equals is correct, but Eclipse says that in the line:
MultiSet<E> o = (MultiSet<E>) object;
there is an unchecked cast from object to Multiset<E>
Any thoughts?
Also, in my toString method, i'm not 100% sure how to define "res"?
Thanks,
// Chris
use this instead:
MultiSet<?> o = (MultiSet<?>) object;
this is necessary due to how generics are implemented in java.

Categories