Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
poopiehead
Oct 6, 2004

Incoherence posted:

1. First rule of hashCode(): if two objects have the same hashCode(), equals() should return true on them as well. The converse is usually the part people trip over (overriding equals() but not hashCode()). I'm not sure you keep that invariant, which you should do.

Unless I'm reading this wrong, you got it backwards.

This is a valid, but stupid implementation of a hashcode.
code:
int hashcode()
{
  return 0;
}
if a.equals(b) the a.hashcode() should == b.hashcode()

logically equivalent but put in a different way:

if a.hashcode() != b.hashcode() then a.equals(b) should be false.

Adbot
ADBOT LOVES YOU

poopiehead
Oct 6, 2004

Incoherence posted:

I didn't get it backwards (both directions are equally true), but I should have been more clear about that being an if-and-only-if statement:

If you override either hashCode() or equals(), you should override both such that
a.hashCode() == b.hashCode() iff a.equals(b) (and b.equals(a))

Sorry. That't not correct though. Multiple values can have the same hash code. You want to minimize collisions, but they will happen.

These are both valid hash functions but wouldn't be if a.hashcode()==b.hashcode() -> a.equals(b)

return 0; \\1.hashcode() == 2.hashcode but 1 != 2
return x % 35; \\ 1.hashcode() == 36.hashcode() but 36 != 1

java posted:


public int hashCode()

Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.

The general contract of hashCode is:

* Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
* If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
* It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

poopiehead fucked around with this message at 03:54 on Apr 23, 2008

poopiehead
Oct 6, 2004

It sounds like what you're doing is valid. Try highlighting the variable that isn't getting updated right and pressing ctrl+shift+I and see if it gives you a more up to date picture. You could also try showing the Display view and writing a line of code to access one of the members in question and then hit the run button or highlight + ctrl+shift+I.

poopiehead
Oct 6, 2004

My guess would be ASP/VBScript :(

...could be ASP.NET/VB also though but not likely since there's a raw form tag...

poopiehead fucked around with this message at 00:54 on May 22, 2008

poopiehead
Oct 6, 2004

It looks like it will call the method repeatedly until it throws an exception, which is kind of weird. The point of reflection here might just be to act as a function pointer which is kind of awkward to do in Java. This method can work with any static void method with no arguments..... but I don't think there's really enough information there to actually know what's going on. It might be clearer with the full code of the method and where it's being called.

poopiehead fucked around with this message at 02:14 on May 27, 2008

poopiehead
Oct 6, 2004

LinkedHashMap

poopiehead
Oct 6, 2004

Am I missing something here? Just want to see if I'm missing something obvious. This is an excerpt of a non-blocking queue implementation.

code:
public class LinkedQueue <E> {
    private static class Node <E> {
        final E item;
        final AtomicReference<Node<E>> next;

        Node(E item, Node<E> next) {
            this.item = item;
            this.next = new AtomicReference<Node<E>>(next);
        }
    }

    private AtomicReference<Node<E>> head
        = new AtomicReference<Node<E>>(new Node<E>(null, null));
    private AtomicReference<Node<E>> tail = head;

    public boolean put(E item) {
        Node<E> newNode = new Node<E>(item, null);
        while (true) {
            Node<E> curTail = tail.get();
            Node<E> residue = curTail.next.get();
            if (curTail == tail.get()) {
                if (residue == null) /* A */ {
                    if (curTail.next.compareAndSet(null, newNode)) /* C */ {
                        tail.compareAndSet(curTail, newNode) /* D */ ;
                        return true;
                    }
                } else {
                    tail.compareAndSet(curTail, residue) /* B */;
                }
            }
        }
    }
}
When they assign tail = head, that's a bug right? When you call tail.compareAndSet() it's going to affect head.get() as well.

I know this is basic java, but I doubt myself when it's in an article by Brian Goetz on a popular site and written 2 years ago.

poopiehead
Oct 6, 2004

Thanks for confirming that I'm not crazy.

The OpdenJDK implementation looks ok. tail and head are volatile read-only fields. They use this special atomic reference class that handles all of the writes to the fields using reflection. Hopefully that makes you feel better ;)

poopiehead
Oct 6, 2004

zootm posted:

When I was looking at the OpenJDK one, it looked a lot like both head and tail fields were initialised to the same container instance, and the container instances used the reflection thing to update their "next" and "item" fields. Confusing anyway!

Yeah it's weird. too lazy to copy and paste, but it was like this, more or less....

code:
private volatile Node head = new Node(null,null);
private volatile Node tail = head;

private headUpdater = new AtomicUpdatingReferenceThing("head")
private tailUpdate = new AtomicUpdatingReferenceThing("tail");
Then for reads, they just went directly at the Nodes, for writes, they go through the updaters.

poopiehead
Oct 6, 2004

Entheogen posted:

why do you need @Override anyway? I never used it, and never got any warnings from javac compiler.

Seems like it is something pretty trivial.

For one thing, it prevents you from changing the signature of a method that was meant to override another. Prevents you from doing something like changing your toString() method to toString(String formatString). Your code will compile fine without it, but it's a useful tool. It also makes the code more readable because you know at a glance that it is overriding.

In C#, it's even part of the method signature.

On using @Override with interfaces, it will actually cause a compiler error in Java 5, but will not in Java 6.

poopiehead fucked around with this message at 01:20 on Jun 27, 2008

Adbot
ADBOT LOVES YOU

poopiehead
Oct 6, 2004

Alan Greenspan posted:

I have like 50-75 classes that need to have the same 9 lines:
......


This probably isn't the case, but if the classes can reasonably have a common base class or maybe can be grouped into a few common base classes, it's pretty easy. But unless they genuinely have something else in common, this would probably be a bad idea.

code:

abstract class AbstractListener<T>
{
  private ListenerProvider<T> listeners = new ListenerProvider<T>(); 
  public void addListener(T listener) 
  { 
    listeners.addListener(listener); 
  } 
  public void removeListener(T listener) 
  { 
    listeners.removeListener(listener); 
  }
}

class A extends AbstractListener<ConcreteListenerClass>
{
 ...
}

class B extends AbstractListener<SomeOtherConcreteListenerClass>
{
}

poopiehead fucked around with this message at 06:02 on Jul 2, 2008

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply