Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Why would an add() in a TreeSet subclass fail?

Reply
Thread Tools

Why would an add() in a TreeSet subclass fail?

 
 
Eric Sosman
Guest
Posts: n/a
 
      02-22-2005


Rhino wrote:
> <(E-Mail Removed)> wrote in message
> news:421b6ced$(E-Mail Removed)...
>
>>>As requested, here's a complete example. It compiles fine in my IDE but

>
> the
>
>>>add() fails in both constructors, throwing the IllegalArgumentException;

>
> if
>
>>>I omit the try blocks, the adds invariably return false and proceed
>>>silently.

>>
>>The code does exactly what it should. You return false in your method.
>>So, congratulation, you haven't gone mad yet.
>>

>
> Are you saying that the add() SHOULD fail or are you just congratulating me
> on detecting the failure cleanly and reporting it to the user?
>
> Do you have any idea why the add() fails or what I need to do to make it
> work?


What you seem to be missing is that it's *your* add()
method that fails. You overrode TreeSet's add() with your
own, whose entire body is `return false;' -- so it returns
`false', just as you told it to. Your code never calls
TreeSet's add() method at all.

--
http://www.velocityreviews.com/forums/(E-Mail Removed)

 
Reply With Quote
 
 
 
 
Rhino
Guest
Posts: n/a
 
      02-22-2005

"Eric Sosman" <(E-Mail Removed)> wrote in message
news:cvfuei$pgv$(E-Mail Removed)...
>
>
> Rhino wrote:
> > <(E-Mail Removed)> wrote in message
> > news:421b6ced$(E-Mail Removed)...
> >
> >>>As requested, here's a complete example. It compiles fine in my IDE but

> >
> > the
> >
> >>>add() fails in both constructors, throwing the

IllegalArgumentException;
> >
> > if
> >
> >>>I omit the try blocks, the adds invariably return false and proceed
> >>>silently.
> >>
> >>The code does exactly what it should. You return false in your method.
> >>So, congratulation, you haven't gone mad yet.
> >>

> >
> > Are you saying that the add() SHOULD fail or are you just congratulating

me
> > on detecting the failure cleanly and reporting it to the user?
> >
> > Do you have any idea why the add() fails or what I need to do to make it
> > work?

>
> What you seem to be missing is that it's *your* add()
> method that fails. You overrode TreeSet's add() with your
> own, whose entire body is `return false;' -- so it returns
> `false', just as you told it to. Your code never calls
> TreeSet's add() method at all.
>

As Homer Simpson would say if he were a Java coder, D'OH! Wow, I can't
believe I missed that! Talk about shooting yourself in the foot

Okay, the failure of the add() now makes perfect sense.

It raises another question though. What is the best way to ensure that my
Range class never gets any new members? I want to give it two values in the
constructor - either two discrete values or an array containing two discrete
values - and then I never want anyone to add new values or remove existing
values.

That's why I overrode the add() method to always return false(); I didn't
want to let it add additional values beyond the two supplied via the
constructor.

Rhino


 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      02-22-2005


Rhino wrote:
> [...]
> It raises another question though. What is the best way to ensure that my
> Range class never gets any new members? I want to give it two values in the
> constructor - either two discrete values or an array containing two discrete
> values - and then I never want anyone to add new values or remove existing
> values.
>
> That's why I overrode the add() method to always return false(); I didn't
> want to let it add additional values beyond the two supplied via the
> constructor.


The bad way would be to override add() and addAll() as
you do now, but to invoke super.add() instead of plain add()
in the constructor.

A better way would be to use composition instead of
inheritance. Don't have Range extend TreeSet; have it
contain a TreeSet instance as a private member variable:

public class Range {
private TreeSet set;

public Range(Object u, Object v) {
set = new TreeSet();
set.add(u);
set.add(v);
}

/* ... other fields and methods ... */
}

Points to ponder:

- If the "other fields and methods" don't absolutely
require a TreeSet, `private Set set;' would be better.

- You could make Range implement Set by adding methods
that forwarded to the contained TreeSet.

- You might learn a good deal from reading "Effective
Java" by Joshua Bloch. In particular, Bloch explains
why the first approach suggested above is "bad" and
why the second is "better."

- Why in the ever-lovin' blue-eyed mornin' do you want
to drag out the entire machinery of a TreeSet just to
keep track of two count them two objects? Canaricide
by cannon, that's what it is.

--
(E-Mail Removed)

 
Reply With Quote
 
Rhino
Guest
Posts: n/a
 
      02-22-2005

"Eric Sosman" <(E-Mail Removed)> wrote in message
news:cvg3ac$rvr$(E-Mail Removed)...
>
>
> Rhino wrote:
> > [...]
> > It raises another question though. What is the best way to ensure that

my
> > Range class never gets any new members? I want to give it two values in

the
> > constructor - either two discrete values or an array containing two

discrete
> > values - and then I never want anyone to add new values or remove

existing
> > values.
> >
> > That's why I overrode the add() method to always return false(); I

didn't
> > want to let it add additional values beyond the two supplied via the
> > constructor.

>
> The bad way would be to override add() and addAll() as
> you do now, but to invoke super.add() instead of plain add()
> in the constructor.
>

This is the current version of my Range.add() method; it works fine, even if
the design is bad:

public boolean add(Object object) {

if (size() >= 2) {
return false;
} else {
return super.add(object);
}
}

I'm not quite clear why this is a bad design. It certainly feels kludgey to
have code like 'if (size() >= 2)' but what are the risks and dangers of
leaving this as it is?

> A better way would be to use composition instead of
> inheritance. Don't have Range extend TreeSet; have it
> contain a TreeSet instance as a private member variable:
>
> public class Range {
> private TreeSet set;
>
> public Range(Object u, Object v) {
> set = new TreeSet();
> set.add(u);
> set.add(v);
> }
>
> /* ... other fields and methods ... */
> }
>
> Points to ponder:
>
> - If the "other fields and methods" don't absolutely
> require a TreeSet, `private Set set;' would be better.
>
> - You could make Range implement Set by adding methods
> that forwarded to the contained TreeSet.
>

I'm a little confused: if it is a bad idea to subclass TreeSet for the
limited functionality that I need for reasons of overkill, doesn't the use
of a TreeSet as a private variable raise the same concerns? Either way, I'm
still implementing a TreeSet with all of its overhead when a simpler class
would probably do the job....

> - You might learn a good deal from reading "Effective
> Java" by Joshua Bloch. In particular, Bloch explains
> why the first approach suggested above is "bad" and
> why the second is "better."
>

I'm certainly not opposed to learning how to design better in Java. As I
said at the start of the other thread, my OO design background isn't
particularly strong. First, I haven't had any formal training in OO (for a
variety of reasons). Second, I haven't found a really good explanation of OO
design yet. The attempts I've seen all seem to talk only in Big Concepts
without giving concrete examples that help clarify *exactly* what is meant
by the terms they are using. Without a clear understanding of those first
pages, it feels pointless to go deeper into these explanations so I tend to
move on and do something else.

I'll put Bloch's book on my list of books to investigate and buy a copy if
it communicates better than the other books I've seen on OO design.

If you are saying my current design is bad - and I am perfectly willing to
agree that it probably is! - and Bloch's design is better, does that mean
there is a 'best' out there, i.e. a solution that is even better than
Bloch's? If so, how would I find out what that solution is and HOW IT WORKS?
(I won't learn much if I see a solution that is supposed to be better unless
it comes with an explanation of how it works and why it's better.)

> - Why in the ever-lovin' blue-eyed mornin' do you want
> to drag out the entire machinery of a TreeSet just to
> keep track of two count them two objects? Canaricide
> by cannon, that's what it is.
>

You raise a perfectly valid point and one that I have been mulling over
since someone else mentioned it on the other thread I launched to discuss
the design of my Range class.

I'm not sure this is a _GOOD_ answer but the truth is that I was trying to
imitate the SQL operators IN and BETWEEN. I don't know if you are familiar
with SQL so forgive me if I elaborate on that just a tiny bit.

In SQL, the IN operator gets used like this:

select * from employee
where empno in (1, 2, 5, 6,

The BETWEEN operator gets used like this:

select * from employee
where hiredate between '1990-01-01' and '1999-12-31'

A key feature of both operators is that they are overloaded: IN and BETWEEN
both let you compare a value to either a set or a range of any of the SQL
datatypes as long as the search value and the values in the set or range are
comparable. Therefore, you can do an IN or BETWEEN on Strings, ints, dates,
or whatever.

Since the IN operator can have a (virtually) unlimited number of values in
its argument list, I decided that the Java equivalent of that argument list
would be a Collection, specifically a TreeSet since the algorithm to
determine if a given value was in the Collection seemed likely to be more
efficient if the Collection values were in order. I developed a class
containing static methods that did a variety of INs.

Having decided that the set required by an IN was suited to a TreeSet, it
seemed a logical extension to store the range implied by the BETWEEN
operator in a specialized Collection, specifically a TreeSet containing two
values (where the low value was always first). So, I started developing
specific Range classes, like StringRange and IntRange to handle String and
int ranges respectively. Then I thought I should generalize the solution so
I came up with the concept of the Range class. When I got into trouble
making Range work, I started this thread.

Now that I've fixed the problem with the add() method, this approach seems
to be working and gives me the behaviour I want - at least as far as I've
tested.

On the other hand, this solution is probably massive overkill compared to
what I actually need to properly store ranges so that I can do BETWEENs.

Someone on the other thread suggested doing something a lot simpler so I've
been thinking along the lines of something more like the Point class and
have started work on this simpler Range2 class (I'm calling it Range2 to
distinguish it from Range; if I finally decide to delete Range entirely,
I'll rename Range2 to Range.)

Rhino


 
Reply With Quote
 
Chris Uppal
Guest
Posts: n/a
 
      02-23-2005
Rhino wrote:

> I'm certainly not opposed to learning how to design better in Java. As I
> said at the start of the other thread, my OO design background isn't
> particularly strong. First, I haven't had any formal training in OO (for a
> variety of reasons). Second, I haven't found a really good explanation of
> OO design yet. The attempts I've seen all seem to talk only in Big
> Concepts without giving concrete examples that help clarify *exactly*
> what is meant by the terms they are using.


There are /masses/ of bad books that claim to teach OO. They fall into at
least two camps: one camp confuses "OO" with "the syntax/semantics of
Java/C++/<whatever>" (I assume their authors don't actually understand OO at
all[*]); the other camp goes soaring off into the stratosphere and apparently
forget that OO is just a way to make programming abstractions more amenable to
the intuitions about people (and things, but mostly people) that have been
hard-wired into our brains by millenia of evolution -- i.e. its the very
/opposite/ of abstract!

([*] though they may be good books on the syntax/semantics of
Java/C++/<whatever> in their own right, that doesn't in itself make them good
books to learn OO from.)

FWIW, the best book I know of on this subject is:

Object Design
Roles, Responsibilities, and Collaborations
Rebacca Wirfs-Brock and Alan McKean

That's not a primer -- it assumes that you are interested enough in the subject
to be willing to read a /whole book/ about it (and most programmers would not
be). It's also language neutral (so there's no code in it). OTOH it is
entirely free from UML (I tend to see UML in books as a symptom of falling into
one or other of the camps I mentioned earlier -- though a little bit of it is
OK). It's pretty concrete in that it uses lots of examples and avoids the
theoretical verbiage. But it still is /fairly/ abstract, though, so don't
spend money on it without a chance to browse through it first.

-- chris


 
Reply With Quote
 
Rhino
Guest
Posts: n/a
 
      02-23-2005

"Chris Uppal" <(E-Mail Removed)-THIS.org> wrote in message
news:421c751e$1$38042$(E-Mail Removed).. .
> Rhino wrote:
>
> > I'm certainly not opposed to learning how to design better in Java. As I
> > said at the start of the other thread, my OO design background isn't
> > particularly strong. First, I haven't had any formal training in OO (for

a
> > variety of reasons). Second, I haven't found a really good explanation

of
> > OO design yet. The attempts I've seen all seem to talk only in Big
> > Concepts without giving concrete examples that help clarify *exactly*
> > what is meant by the terms they are using.

>
> There are /masses/ of bad books that claim to teach OO. They fall into at
> least two camps: one camp confuses "OO" with "the syntax/semantics of
> Java/C++/<whatever>" (I assume their authors don't actually understand OO

at
> all[*]); the other camp goes soaring off into the stratosphere and

apparently
> forget that OO is just a way to make programming abstractions more

amenable to
> the intuitions about people (and things, but mostly people) that have been
> hard-wired into our brains by millenia of evolution -- i.e. its the very
> /opposite/ of abstract!
>
> ([*] though they may be good books on the syntax/semantics of
> Java/C++/<whatever> in their own right, that doesn't in itself make them

good
> books to learn OO from.)
>

I'm glad to hear it isn't only me that has had these experiences; I was
beginning to think I just wasn't very bright....

> FWIW, the best book I know of on this subject is:
>
> Object Design
> Roles, Responsibilities, and Collaborations
> Rebacca Wirfs-Brock and Alan McKean
>
> That's not a primer -- it assumes that you are interested enough in the

subject
> to be willing to read a /whole book/ about it (and most programmers would

not
> be). It's also language neutral (so there's no code in it). OTOH it is
> entirely free from UML (I tend to see UML in books as a symptom of falling

into
> one or other of the camps I mentioned earlier -- though a little bit of it

is
> OK). It's pretty concrete in that it uses lots of examples and avoids the
> theoretical verbiage. But it still is /fairly/ abstract, though, so don't
> spend money on it without a chance to browse through it first.
>

Thanks for the suggestion; I'll have a look for that book and see if it
speaks to me as clearly as it does to you

Rhino


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-23-2005


Rhino wrote:
> [trying to extend TreeSet but ensure that two and only two
> objects are ever inserted into it]
>
> This is the current version of my Range.add() method; it works fine, even if
> the design is bad:
>
> public boolean add(Object object) {
>
> if (size() >= 2) {
> return false;
> } else {
> return super.add(object);
> }
> }
>
> I'm not quite clear why this is a bad design. It certainly feels kludgey to
> have code like 'if (size() >= 2)' but what are the risks and dangers of
> leaving this as it is?


.... and you've overridden addAll() as well, to make sure nobody
can insert an unwanted object into your TreeSet that way, either.
Fine, you've locked all the doors.

.... except that TreeSet offers clear() and remove() methods
that a client could use to delete one or both of the "two and
only two" objects after your Range is constructed. Do you
want to prevent that? Then get busy and write a few more
overrides to lock those two doors. TreeSet also has iterator(),
and a client could use the returned Iterator object to muck
with your Range. Do you want to prevent that? More busy work.
And what about the subSet(), tailSet(), and headSet() methods?
Haul out your editor and write still more overrides ...

Eventually, after many overrides, you'll have locked all
the doors and made your Range unmodifiable. But wait! Acceding
to enormous community pressure, Java 1.7 comes along and defines
a new addFiltered(Collection, Filter) method to all the modifiable
collections. A new door has suddenly opened in your fortress
wall, and the Orcs are charging through it ... Your nightmare
never ends.

>> A better way would be to use composition instead of
>>inheritance. Don't have Range extend TreeSet; have it
>>contain a TreeSet instance as a private member variable:

>
> I'm a little confused: if it is a bad idea to subclass TreeSet for the
> limited functionality that I need for reasons of overkill, doesn't the use
> of a TreeSet as a private variable raise the same concerns? Either way, I'm
> still implementing a TreeSet with all of its overhead when a simpler class
> would probably do the job....


If Range extends TreeSet, it automatically exposes all of
TreeSet's behaviors and characteristics that you don't explicitly
override. If Range instead *contains* a TreeSet instance, you
can choose to expose only those characteristics you want. In
particular, if the TreeSet instance is private within Range and
if Range offers no method that lets a client get hold of the
TreeSet reference, there is no way the client can call any methods
on the TreeSet; only your Range class itself has the means to
modify the TreeSet, and there's no way to do an end-run around
your protective blockade.

>> - Why in the ever-lovin' blue-eyed mornin' do you want
>> to drag out the entire machinery of a TreeSet just to
>> keep track of two count them two objects? Canaricide
>> by cannon, that's what it is.
>>

> [trying to do something analogous to SQL's IN and BETWEEN]
> Since the IN operator can have a (virtually) unlimited number of values in
> its argument list, I decided that the Java equivalent of that argument list
> would be a Collection, specifically a TreeSet since the algorithm to
> determine if a given value was in the Collection seemed likely to be more
> efficient if the Collection values were in order. I developed a class
> containing static methods that did a variety of INs.
>
> Having decided that the set required by an IN was suited to a TreeSet, it
> seemed a logical extension to store the range implied by the BETWEEN


Here, I think, is where you go wrong. What's sauce for the
goose is sauce for the gander, but tastes perfectly awful atop
calamari. It is true you could model a range as the set of all
elements within the range (back off, mathematicians: there are
no non-denumerable sets on a finite computer), but that's not a
great model. All you really care about are the endpoints of the
range, and you'll use comparisons to decide whether a test item
does or doesn't lie between them. Note, too, that a range requires
an ordering notion while a set does not: you could speak of a set
of points on the plane, but you cannot speak of a range of points
on the plane (mathematicians: anybody who mentions space-filling
curves is out of, er, line).

Since ranges and sets are different in so many ways, there
seems little reason to base them on the same data structure.
Start by deciding on the behaviors you want; then and only
then start thinking about the data structures to support them.

--
(E-Mail Removed)

 
Reply With Quote
 
Rhino
Guest
Posts: n/a
 
      02-24-2005

"Eric Sosman" <(E-Mail Removed)> wrote in message
news:cvic6c$2o5$(E-Mail Removed)...
>
>
> Rhino wrote:
> > [trying to extend TreeSet but ensure that two and only two
> > objects are ever inserted into it]
> >
> > This is the current version of my Range.add() method; it works fine,

even if
> > the design is bad:
> >
> > public boolean add(Object object) {
> >
> > if (size() >= 2) {
> > return false;
> > } else {
> > return super.add(object);
> > }
> > }
> >
> > I'm not quite clear why this is a bad design. It certainly feels kludgey

to
> > have code like 'if (size() >= 2)' but what are the risks and dangers of
> > leaving this as it is?

>
> ... and you've overridden addAll() as well, to make sure nobody
> can insert an unwanted object into your TreeSet that way, either.
> Fine, you've locked all the doors.
>
> ... except that TreeSet offers clear() and remove() methods
> that a client could use to delete one or both of the "two and
> only two" objects after your Range is constructed. Do you
> want to prevent that? Then get busy and write a few more
> overrides to lock those two doors. TreeSet also has iterator(),
> and a client could use the returned Iterator object to muck
> with your Range. Do you want to prevent that? More busy work.
> And what about the subSet(), tailSet(), and headSet() methods?
> Haul out your editor and write still more overrides ...
>
> Eventually, after many overrides, you'll have locked all
> the doors and made your Range unmodifiable. But wait! Acceding
> to enormous community pressure, Java 1.7 comes along and defines
> a new addFiltered(Collection, Filter) method to all the modifiable
> collections. A new door has suddenly opened in your fortress
> wall, and the Orcs are charging through it ... Your nightmare
> never ends.
>

Ok, you've made your point I see the dangers now.

> >> A better way would be to use composition instead of
> >>inheritance. Don't have Range extend TreeSet; have it
> >>contain a TreeSet instance as a private member variable:

> >
> > I'm a little confused: if it is a bad idea to subclass TreeSet for the
> > limited functionality that I need for reasons of overkill, doesn't the

use
> > of a TreeSet as a private variable raise the same concerns? Either way,

I'm
> > still implementing a TreeSet with all of its overhead when a simpler

class
> > would probably do the job....

>
> If Range extends TreeSet, it automatically exposes all of
> TreeSet's behaviors and characteristics that you don't explicitly
> override. If Range instead *contains* a TreeSet instance, you
> can choose to expose only those characteristics you want. In
> particular, if the TreeSet instance is private within Range and
> if Range offers no method that lets a client get hold of the
> TreeSet reference, there is no way the client can call any methods
> on the TreeSet; only your Range class itself has the means to
> modify the TreeSet, and there's no way to do an end-run around
> your protective blockade.
>

Excellent! That answers my question very clearly. That makes a great deal of
sense.

For some reason, I got it into my head that using a TreeSet as my foundation
was bad at least partially because it had so much overhead so that using
composition reduced that overhead somehow; I was trying to figure out how
that would work. Now I see that the real benefit is that you get far better
security/stability since the TreeSet is totally internal to the Range.

> >> - Why in the ever-lovin' blue-eyed mornin' do you want
> >> to drag out the entire machinery of a TreeSet just to
> >> keep track of two count them two objects? Canaricide
> >> by cannon, that's what it is.
> >>

> > [trying to do something analogous to SQL's IN and BETWEEN]
> > Since the IN operator can have a (virtually) unlimited number of values

in
> > its argument list, I decided that the Java equivalent of that argument

list
> > would be a Collection, specifically a TreeSet since the algorithm to
> > determine if a given value was in the Collection seemed likely to be

more
> > efficient if the Collection values were in order. I developed a class
> > containing static methods that did a variety of INs.
> >
> > Having decided that the set required by an IN was suited to a TreeSet,

it
> > seemed a logical extension to store the range implied by the BETWEEN

>
> Here, I think, is where you go wrong. What's sauce for the
> goose is sauce for the gander, but tastes perfectly awful atop
> calamari. It is true you could model a range as the set of all
> elements within the range (back off, mathematicians: there are
> no non-denumerable sets on a finite computer), but that's not a
> great model. All you really care about are the endpoints of the
> range, and you'll use comparisons to decide whether a test item
> does or doesn't lie between them. Note, too, that a range requires
> an ordering notion while a set does not: you could speak of a set
> of points on the plane, but you cannot speak of a range of points
> on the plane (mathematicians: anybody who mentions space-filling
> curves is out of, er, line).
>
> Since ranges and sets are different in so many ways, there
> seems little reason to base them on the same data structure.
> Start by deciding on the behaviors you want; then and only
> then start thinking about the data structures to support them.
>

Fair enough; as I said, I didn't really think it through very thoroughly
before going with a TreeSet: I just got the notion that a Range was a very
specialized set and therefore merited being a TreeSet just like the IN sets.
I didn't realize all the consequences that you have pointed out so well.

For what it's worth, I now have a SimpleRange class, which subclasses
Object, that does all of what I need it to do to meet my needs without
carrying around all the baggage of the TreeSet. Just for the heck of it,
here it is. If you can see any problems or omissions in it, I'd be delighted
to hear about it. I'm not sure I've covered everything we've talked about
but I tried. I've also used JUnit to test everything; I probably haven't
thrown as many exotic cases at it as I should but every test I have given it
passed. By the way, I initially assumed that my Range or SimpleRange class
would have to be further subclassed to handle specific datatypes but I'm
starting to think that won't be necessary; thanks to polymorphism, this baby
might just do the whole job


/**
* Class SimpleRange describes the behaviour of all ranges, regardless of
the class of
* data stored in it.
*
* <p>A SimpleRange is a class containing exactly two elements of the same
type. These
* elements represent the end-points of a range of values, e.g. 18 to 21 or
A to E.</p>
*
* @author Rhino
*
*/
public class SimpleRange {

public static int NUMBER_OF_ELEMENTS = 2;

Comparable lowValue = null;
Comparable highValue = null;

/**
* Constructor SimpleRange(Comparable, Comparable) creates an instance
of the class.
*
* @param Comparable
* firstObject one of the two Object values that will
encompass
* the range
* @param Comparable
* secondObject the other of the two Object values that will
encompass
* the range
*/
public SimpleRange(Comparable firstObject, Comparable secondObject) {

/* Verify that neither object is null. */
if (firstObject == null) {
throw new IllegalArgumentException("The first Object cannot be
null.");
}

if (secondObject == null) {
throw new IllegalArgumentException("The second Object cannot be
null.");
}

/*
* Since only Comparable objects are permitted by this constructor,
compare them
* and store the lower one in the lowValue class variable. Store the
other one in the
* highValue class variable.
*/
try {
if (firstObject.compareTo(secondObject) > 0) {
highValue = firstObject;
lowValue = secondObject;
} else {
lowValue = firstObject;
highValue = secondObject;
}
} catch (ClassCastException cc_excp) {
throw new IllegalArgumentException("The first Object, " +
firstObject.toString() + ", belongs to class " +
firstObject.getClass().getName() + ". The second Object, " +
secondObject.toString() + ", belongs to class " +
secondObject.getClass().getName() + ". Both Objects implement the Comparable
interface but they cannot be compared with each other.");
}

}

/**
* Constructor SimpleRange(Comparable[]) creates an instance of the
class.
*
* @param Object[]
* range an array of Comparables
*/
public SimpleRange(Comparable[] range) {

/* Verify that the array is not null. */
if (range == null) {
throw new IllegalArgumentException("The range array cannot be
null.");
}

/* Verify that the array contains exactly two elements. */
if (range.length != 2) {
throw new IllegalArgumentException(
"The range array must contain exactly two elements.");
}

/* Verify that the array elements aren't null. */
if (range[0] == null) {
throw new IllegalArgumentException("The first array element
cannot be null.");
}

if (range[1] == null) {
throw new IllegalArgumentException("The second array element
cannot be null.");
}

/*
* Since only Comparable objects are permitted by this constructor,
compare them
* and store the lower one in the lowValue class variable. Store the
other one in the
* highValue class variable.
*/
try {
if (range[0].compareTo(range[1]) > 0) {
lowValue = range[1];
highValue = range[0];
} else {
lowValue = range[0];
highValue = range[1];
}
} catch (ClassCastException cc_excp) {
throw new IllegalArgumentException("The first Object, " +
range[0].toString() + ", belongs to class " + range[0].getClass().getName()
+ ". The second Object, " + range[1].toString() + ", belongs to class " +
range[1].getClass().getName() + ". Both Objects implement the Comparable
interface but they cannot be compared with each other.");
}

}

/**
* Method size() returns the size of this SimpleRange; the value will
always be 2.
*
* @return the size of this SimpleRange (always 2)
*/
public int size() {

return NUMBER_OF_ELEMENTS;
}

/**
* Method getValues() returns all of the values in this SimpleRange.
*
* @return all of the values in this SimpleRange
*/
public Comparable[] getValues() {

Comparable[] values = new Comparable[size()];

values[0] = lowValue;
values[1] = highValue;

return values;
}

/**
* Method getLow() returns the lower of the two values in the
SimpleRange.
*
* @return Comparable the lower of the two values in the SimpleRange
*/
public Comparable getLow() {

return lowValue;
}

/**
* Method getHigh() returns the higher of the two values in the
SimpleRange.
*
* @return Comparable the higher of the two values in the SimpleRange
*/
public Comparable getHigh() {

return highValue;
}

/**
* This version of between() is a convenience method that determines if
a given int
* value is within a range of int values.
*
* <p>This version of between() will return true if the input value
matches
* either end-point of the range or lies anywhere between them.</p>
*
* @param Comparable input the value which is being compared to the
range
* @return boolean true if the input value is equal to either endpoint
or lies between them, otherwise false
*/
public boolean between(Comparable input) {

return between(true, input, true);
}


/**
* This version of between() determines if a given value is within a
range of values.
*
* <p>Since different users have different expectations about the
behaviour of a
* between method, this method provides two booleans that control which
behaviour
* will be experienced. For example, if the user desires between to be
true if the input
* value is strictly between the two endpoints but not equal to any of
them, both booleans
* should be set to false.</p>
*
* @param includesLow if true the low end of the range should include
the low value, otherwise the low end of the range starts just above the low
value
* @param input the value that is being compared to the range
* @param includesHigh if true the high end of the range should include
the high value, otherwise the high end of the range ends just below the high
value
* @return true if the input value is in the range, otherwise false
*/
public boolean between(boolean includesLow, Comparable input, boolean
includesHigh) {

/*
* If 'includesLow' and 'includesHigh' are both true, return true if
'input'
* satisfies this condition: lowValue <= input <= highValue.
*/
if (includesLow && includesHigh) {
try {
if (input.compareTo(lowValue) >= 0 &&
input.compareTo(highValue) <= 0) {
return true;
} else {
return false;
}
} catch (ClassCastException cc_excp) {
throw new IllegalArgumentException("The input value, " +
input.toString() + ", belongs to class " + input.getClass().getName() + ".
Although the end-points of the range can be compared with each other, they
cannot be compared with the input value.");
}
}
else
/*
* If 'includesLow' and 'includesHigh' are both false, return true
if 'input'
* satisfies this condition: lowValue < input < highValue.
*/
if (!includesLow && !includesHigh) {
try {
if (input.compareTo(lowValue) > 0 &&
input.compareTo(highValue) < 0) {
return true;
} else {
return false;
}
} catch (ClassCastException cc_excp) {
throw new IllegalArgumentException("The input value, " +
input.toString() + ", belongs to class " + input.getClass().getName() + ".
Although the end-points of the range can be compared with each other, they
cannot be compared with the input value.");
}
}
else
/*
* If 'includesLow' is true and 'includesHigh' is false, return true
if 'input'
* satisfies this condition: lowValue <= input < highValue.
*/
if (includesLow && !includesHigh) {
try {
if (input.compareTo(lowValue) >= 0 &&
input.compareTo(highValue) < 0) {
return true;
} else {
return false;
}
} catch (ClassCastException cc_excp) {
throw new IllegalArgumentException("The input value, " +
input.toString() + ", belongs to class " + input.getClass().getName() + ".
Although the end-points of the range can be compared with each other, they
cannot be compared with the input value.");
}
}
else
/*
* If 'includesLow' is false and 'includesHigh' is true, return true
if 'input'
* satisfies this condition: lowValue < input <= highValue.
*/
if (!includesLow && includesHigh) {
try {
if (input.compareTo(lowValue) > 0 &&
input.compareTo(highValue) <= 0) {
return true;
} else {
return false;
}
} catch (RuntimeException excp) {
throw new IllegalArgumentException("The input value, " +
input.toString() + ", belongs to class " + input.getClass().getName() + ".
Although the end-points of the range can be compared with each other, they
cannot be compared with the input value.");
}
}
else {
return false;
}
}
}






 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Subclass of subclass Fab C++ 0 08-09-2012 09:54 AM
subclass a class in the namespace of the that subclass Trans Ruby 8 10-23-2008 07:24 AM
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
String subclass method returns subclass - bug or feature? S.Volkov Ruby 2 03-12-2006 06:46 PM
subclass has a variable that is subclass of same superclass jstorta Java 3 02-20-2006 08:42 PM



Advertisments