Java: add element after an element in the LinkedList - java

I want to add an element after an element in the list if list already contain that element otherwise I want to add this new element to beginning
of the list.
Somehow below code is not working.
Any suggestions?
Does this approach correct performance wise?
public class HelloWorld
{
public static void main(String[] args) {
LinkedList<Task> l =new LinkedList<Task>();
l.add(new Task("a"));
l.add(new Task("b"));
l.add(new Task("c"));
int index;
if((index = l.lastIndexOf(new Task("a"))) != -1){
l.add(++index, new Task("5"));
}else{
l.addFirst(new Task("6"));
}
System.out.println(l);
}
}
class Task{
String value;
Task(String v){
value = v;
}
public boolean equals(Task t){
return t.value.equals(this.value);
}
public String toString(){
return this.value;
}
}
Output produces: [6,a,b,c]
Expected output: [a,5,b,c]

You are not overriding Object#equals in your Task class.
You need to parametrize it with Object, otherwise it's an overload.
That in turn doesn't allow your new Task("a") to be equal to new Task("a"), as Object.equals in invoked instead, and the references don't match.
This in turn will cripple your lastIndexOf invocation with unexpected results.
Example
#Override
public boolean equals(Object obj) {
// TODO your code, i.e. based on the "value" field
}
If you're using an IDE (which I recommend), you will have features allowing to draft equals (and hashCode) implementations based on your desired properties.

Your equals should look like that.
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Task task = (Task) o;
return value != null ? value.equals(task.value) : task.value == null;
}

Related

Set of object contains by object with value (not reference) (java 7)

I have my object with some feilds.
public class MyObject{
private String a;
private String b;
}
I have a Set contains objects like this :
Set<MyObject> thirdSet = new HashSet<MyObject>();
Set<MyObject> firstSet=getFirstSet();
Set<MyObject> secondSet = getSecondeSet();
for (MyObjectobj : firstSet) {
if (!secondSet.contains(obj)) {
thirdSet.add(obj);
}
}
I need to select all obj that not contains in my secondSet into thridSet (obj with value not by reference)
Is it possible or using collection is more better?
You'll need to override both equals and hashcode methods in your object. I'd recommend using the java 7 Objects utility methods if you can to prevent NullPointerExceptions.
#Override
public boolean equals(Object other) {
if (!(other instanceof MyObject)) {
return false;
}
MyObject that = (MyObject) other;
return Objects.equals(a, that.a) && Objects.equals(b, that.b);
}
#Override
public int hashcode() {
Objects.hash(a, b);
}
I'd also recommend taking a look at the third party library Guava if possible which would simplify your code.
Set<MyObject> thirdSet = new HashSet<>(Sets.difference(firstSet, secondSet));
Note wrapping it in a new HashSet so it can be modified (if you don't need to modify it you can remove that)
You should override Object#equals and Object#hashCode in MyObject.java.
#Override
public boolean equals(Object o) {
if (!(o instanceof MyObject)) {
return false;
}
MyObject m = (MyObject) o;
return a.equals(m.a) && b.equals(m.b);
}
#Override
public int hashCode() {
return Objects.hash(a, b);
}
Also if you're allowed to use external libraries, you should check out Guava's Sets#difference.

Java ArrayList does not use overriden equals(Object o) method to compare

Why does ArrayList's contains(Object o) does not run my overridden equals(Object o) method? Consider this code:
private class TargetRC {
public RComponent rc;
public TargetRC(RComponent e) {
rc = e;
}
#Override
public boolean equals(Object o) {
if (o instanceof RComponent)
return o == rc;
else
return o == this;
}
}
private ArrayList<TargetRC> list = new ArrayList<TargetRC>();
public void add(RComponent e) {
list.add(new TargetRC(e));
System.out.println(list.contains(e));
}
As you see it is:
Symetric because o == rc when and only when rc == o
Reflexive because rc == rc
for any RComponent used in comparison.
Adding any element through visible here add method prints always false. No println works inside the equals method. Changing == operators to equals does not make any difference. What is wrong here?
You test
list.contains(e)
with e being a RComponent.
So the list calls RComponent.equals(Object) for every element in your list
which always returns false.
Ok, only thing I had to do was to override ArrayList's indexOf method like this:
private ArrayList<TargetRC> list = new ArrayList<TargetRC>(){
#Override
public int indexOf(Object o){
for(int i=0; i<size(); ++i){
if(get(i).equals(o)) return i;
}
return -1;
}
};

java override equals() in custom class

I'm trying to Override the vertex variable equals. Currently when vertexList.contains("test") is called, the equals() declared in the vertex class isn't ran. Is there something I'm missing?
The full code can be found on my git hub if you think it's something else, along with a quick test file UI.java. Otherwise I'm out of ideas.
Thanks,
class Data implements Graph
{
java.util.LinkedList<vertex> vertexList = new java.util.LinkedList<vertex>();
class vertex
{
String ID;
java.util.LinkedList<String> links = new java.util.LinkedList<String>();
boolean tracker = false;
public vertex(String it)
{
ID = it;
}
#Override
public boolean equals(Object obj)
{
if (obj.equals(null))
return false;
System.err.println("OBJECT CHECK");
String str = (String) obj;
// return true; //To test if it's being accessed
return str.equals(ID);
}
public String toString()
{
return ID;
}
}
}
Executing vertexList.contains("test") will execute the equals() method of String against your object. You're looking for linkedList.contains(new Vertex("a")); which will execute your equals() method against a target object. Here's the linkedlist impl for contains() where o is the object being searched for.
for (Entry e = header.next; e != header; e = e.next) {
if (o.equals(e.element))
return index;
index++;
}
You should also be checking for a Vertex instead of a String in the equals() method. That is what it is meant for. You should be trying to check if one Vertex equals another.
What are you trying to accomplish in this line?
String str = (String) obj;
If I understood the purpose of your code correctly, I think your equals method should look more like this:
#Override
public boolean equals(Object obj){
if( obj != null && obj.getClass().equals(this.getClass()){
return ((vertex)obj).toString().equals(this.ID)
} else {
return false;
}
}

Does Collection's contain method ever return false for an instance added to it?

I was going through Joshua Bloch's online Chapter on "overridding equals() method".
Here's the link.
The following section confuses me,
Reflexivity—The first requirement says merely that an object must be
equal to itself. It is hard to imagine violating this requirement
unintentionally. If you were to violate it and then add an instance of
your class to a collection, the collection’s contains method would
almost certainly say that the collection did not contain the instance
that you just added.
Question - Is it possible for a collection's contain method to return false on an instance added to it?
I tried but the result returned is always true.
To illustrate the point, have this simple class:
class C {
private int i;
public C(int i) { this.i = i; }
}
Now, if you do:
C c1 = new C(1);
C c2 = new C(1);
List<C> l = new ArrayList<C>();
l.add(c1);
l.contains(c2) will return false, since c2.equals(c1) is false, in spite of the fact that both instances have the same constructor arguments.
This is because class C does not override .equals() nor .hashCode().
In general, each time your class is bound to be used in a Collection of any kind, you had better override both of these methods. In this case:
// Note: final class, final member -- that makes this class immutable
final class C {
private final int i;
public C(int i) { this.i = i; }
#Override
public int hashCode() { return i; }
#Override
public boolean equals(Object o)
{
// no object equals null
if (o == null)
return false;
// an object is always equal to itself
if (this == o)
return true;
// immutable class: if the class of the other is not the same,
// objects are not equal
if (getClass() != o.getClass())
return false;
// Both objects are of the same class: check their members
return i == ((C) o).i;
}
}
Question - Is it possible for a collection's contain method to return false on an instance added to it?
Not unless the added object's equals() violates the contract, as the quote from the book explains.
As suggested by #Karthik T, try this with an object whose equals() unconditionally returns false (thereby violating the contract).
Here is a demonstration of a collection's contains method returning false for an object that has just been added to the collection. I took a normal equals and hashCode, generated by Eclipse, and changed the equals method to be non-reflexive. Specifically, it returns false when comparing an object to itself.
import java.util.LinkedList;
import java.util.List;
public class Test {
int someValue;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + someValue;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
// Bad. Non-reflexive. Should return true.
return false;
}
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Test other = (Test) obj;
if (someValue != other.someValue)
return false;
return true;
}
public static void main(String[] args) {
List<Test> myList = new LinkedList<Test>();
Test myObject = new Test();
myList.add(myObject);
System.out.println(myList.contains(myObject));
}
}

MultiSet: problems with add, remove and equals

i have some problems with some of my methods for my MultiSet class.
This is a tester, and MultiSet class should get the output: "Succes!" if it works correctly.
This is the tester:
public class MultiSetTest {
public static void main(String[] args) {
MultiSet<String> a = new MultiSet<String>();
MultiSet<String> b = new MultiSet<String>();
a.add("Foo");
a.add("Bar");
a.add("Foo");
System.out.println("a:" + a); // test toString
b.add("Bar");
b.add("Foo");
b.add("Bar");
b.add("Foo");
System.out.println("b:" + b);
assert !a.equals(b) : "Failed test 1!"; // test equals
assert b.remove("Bar") : "Failed test 2!"; // test remove
assert a.equals(b) : "Failed test 3!";
for(String s : a) { // test iterator
assert b.remove(s) : "Failed test 4!";
}
assert b.size() == 0 : "Failed test 5!";
Set<String> baseSet = new HashSet<String>(a);
assert baseSet.size()==2 : "Failed test 6!";
b = new MultiSet<String>(a);
assert a.equals(b) : "Failed test 7!";
try {
assert false;
System.out.println("Please enable assertions!");
}
catch(AssertionError e) {
System.out.println("Success!");
}
}
}
And my Multiset 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);
}
public boolean add()
{
return false;
}
public boolean remove()
{
return false;
}
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)
{
current = iterator.next();
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;
}
}
Maybe if you could help me on the way with either add or remove, then i can probably work the other one out.
Also, my equals doesn't appear to work correctly,
and I'm unsure about how to work out "res" at String toString. Don't mind my return statement, i'll throw in some brackets etc. later to make it look good.
Thank you for your help.
// Chris
Why not on of use well-tested Google Guavas's Multisets instead of reinventing the wheel? You can choose one of many implementations:
ConcurrentHashMultiset,
EnumMultiset,
ForwardingMultiset,
HashMultiset,
ImmutableMultiset,
LinkedHashMultiset,
TreeMultiset
what should cover your use case or - if you really want - implement Multiset interface by yourself, looking into sources of default implemntations.
EDIT:
Your implementation breaks Collecion interface contract - you cannot return false for add(E e). Read Collection docs:
boolean add(E e)
Parameters:
e - element whose presence in this collection is to be ensured
Returns:
true if this collection changed as a result of the call
Throws:
UnsupportedOperationException - if the add operation is not supported by this collection
If you want to use read-only Multiset use either ImmutableMultiset (more specifically ImmutableMultiset.copyOf(Iterable)) or implement Multiset
's interface add(E e) method throwing UnsupportedOperationException.

Categories