Instance Variable vs Local Variable

P

Paul Carey

Hi

When delegating a compareTo method for a playing card to a Comparator, I
wasn't sure whether to go for the instance variable or local variable approach:

public class Card implements Comparable
{
static class SortByValueThenSuit implements Comparator
{
public int compare(Object o1, Object o2)
{
...
}
}

// local variable approach
public int compareTo(Object o)
{
return new SortByValueThenSuit().compare(this, o);
}


// instance variable approach
private SortByValueThenSuit sorter = new SortByValueThenSuit();
public int compareTo(Object o)
{
return sorter.compare(this, o);
}
}

With only 52 cards in the deck and with a fairly limited number of comparisons,
maybe the local variable option would be considered better for reasons of
encapsulation and because the Comparator will be automatically marked for
garbage collection once the method has exited. But I'm curious to know under
what kind of circumstances might the overhead of creating a new Comparator
every time compareTo is invoked mean that the instance variable approach
would be preferable. If there are a very large number of objects to be sorted
and sorting occurs regularly, am I going to be wasting memory, or is the fact
that the Comparator contains no instance variables itself relevant?

Many thanks

Paul
 
V

VisionSet

Paul Carey said:
Hi

When delegating a compareTo method for a playing card to a Comparator, I
wasn't sure whether to go for the instance variable or local variable approach:

public class Card implements Comparable
{
static class SortByValueThenSuit implements Comparator
{
public int compare(Object o1, Object o2)
{
...
}
}

// local variable approach
public int compareTo(Object o)
{
return new SortByValueThenSuit().compare(this, o);
}


// instance variable approach
private SortByValueThenSuit sorter = new SortByValueThenSuit();
public int compareTo(Object o)
{
return sorter.compare(this, o);
}
}

Instantiation is always expensive, don't do it more often than neccessary.
I see no value in the local variable approach for any number of comparisons,
unless you retrieve the same instance each time.
 
C

Chris Smith

Paul said:
Hi

When delegating a compareTo method for a playing card to a Comparator, I
wasn't sure whether to go for the instance variable or local variable approach:


// local variable approach
public int compareTo(Object o)
{
return new SortByValueThenSuit().compare(this, o);
}


// instance variable approach
private SortByValueThenSuit sorter = new SortByValueThenSuit();
public int compareTo(Object o)
{
return sorter.compare(this, o);
}

In general, Comparator implementations belong to a general class of
"stateless" objects. That is, the important thing about them is their
behavior, not their state, so that one instance is as good as any other.
When that's the case, there's simply no benefit to creating multiple
instances. I would create one Comparator and store it in a field. I'd
even be tempted to make it a public static final field, so that others
can choose to use that ordering explicitly when sorting.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Uppal

Paul said:
When delegating a compareTo method for a playing card to a Comparator, I
wasn't sure whether to go for the instance variable or local variable
approach:

Taking your code at face value, the local variable approach is the most
"natural" whereas the instance variable version can be seen as a slightly
convoluted optimisation of the same logic. Looked at that way, then the
standard advice is not to optimise unless you know it makes a useful
difference -- i.e. if you have reason to suppose (say from profiling) that the
comparison is a bottleneck for your application(s) then you would try the
optimised version and measure the difference. If -- note that: *IF* -- it
turned out to be usefully faster then you'd keep the optimisation.

However, in this case I can't see why you are creating a SortByValueThenSuit
object at all -- I'd have expected a Card to know how to compare itself to
another card. If you need Comparators (especially if different contexts use
different comparison policies) then the context would create one that forwards
to the cards' own comparison. There's also nothing to stop you creating a
fixed set of pre-defined Comparator objects (1 or more, embodying whatever
policies are most useful) and assigning them to static variables in the Card
class. (But that's just a convenience, note.)

I.e. something like (completely untested)

class Card implements Comparable
{
//...

/** implements "standard" comparison by value then suite */
public int
compareTo(Object o)
{
Card other = (Card)o.
if (other.value() < this.value())
return -1;
if (other.value() > this.value())
return +1;
if (other.suite() < this.suite())
return -1;
if (other.suite() > this.suite())
return +1;
return 0;
}

// you may want to override equals() & hash() too
}


Then in other code somewhere, we can make a SortedSet of Cards. This example
will use the natural ordering of the Cards defined by the Card.compareTo()
method:
SortedSet inOrder = new TreeSet();
inOrder.add(... a card...);
inOrder.add(... another card...);

Or we could make a reversed SortedSet of Cards using the our own comparator
that sorts in reverse direction:
Comparator comparator =
new Comparator()
{
public int compare(Object o1, Object o2)
{
// NB: arguments are reversed
return (Card)o2->compareTo(o1);
}
};
SortedSet reversed = new TreeSet(comparator);
reversed.add(... a card...);
reversed.add(... another card...);

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top