10 Replies - 6848 Views - Last Post: 02 February 2012 - 06:29 PM

#1 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Preferences in implementing a pair of integers

Posted 27 January 2012 - 09:18 AM

Hi everybody,

When I was thinking about creating a class to encapsulate a pair of integers recently (which I didn't end up doing anyway), I noticed something interesting about the way other people tended to do it. Just for curiosity's sake, I looked on this and other forums, and it seems like invariably people create a generic class to handle a pair of integers.

I couldn't help thinking, though, that this seemed like overkill, at least for the integer pair case. I've always preferred to just use a Point for this application, and explain when the point is created that it isn't actually coordinates, but a pair of related values. I've used this mechanism many times, but I've never seen anyone else do it.

Does anyone else do this, or am I really the only one? I can't see anything inherently wrong with the idea, but someone might disagree with me, I'm sure. What are everyone else's thoughts about it -- good use of what we're already given, or questionable kludge?

Thanks,
Zel2008

Is This A Good Question/Topic? 3
  • +

Replies To: Preferences in implementing a pair of integers

#2 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2264
  • View blog
  • Posts: 9,470
  • Joined: 29-May 08

Re: Preferences in implementing a pair of integers

Posted 27 January 2012 - 11:28 AM

I'm curious also.
What are the pros and cons of each version? Does the generic version have runtime penalty?
Was This Post Helpful? 0
  • +
  • -

#3 jon.kiparsky  Icon User is offline

  • Pancakes!
  • member icon


Reputation: 7807
  • View blog
  • Posts: 13,203
  • Joined: 19-March 11

Re: Preferences in implementing a pair of integers

Posted 27 January 2012 - 12:02 PM

No, library objects don't get any particular penalty. Both would run the same, assuming your Pair class wasn't written in some ridiculously broken way.

Here's my take on the pros and cons:
The cons of using the Point class are that it fails to communicate the true intent. After all, this is not in fact a point that we're representing. It's a pair of numbers. Source code should always strive to communicate intent, so this is a problem, though how much of a problem is something of a judgement call. The other con would be that the Point class has a lot of methods that you don't need for the Pair, and it might not have things that you do need, so it's not exactly the right tool. It'd just be a bag of data with a lot of inappropriate capabilities. The getter methods would also fail to communicate intent correctly, unless the members of your pair happen to be actually named "x" and "y". (are you sure that's not a point, in that case?)

The main point in favor of using Point is that it exists. You don't have to write a new class, which is only a minimal savings, and the person reading the code will know what it is they're looking at already, which is much more of a savings.

The pros and cons of writing a new Pair class would be the inverse of the above: you have to write a new class, and the person reading the code has to make sure they understand what it is and what it can do. And the Pair class would be obviously representing a pair of numbers, and it would have the methods it needs.


In my view, it's worth taking the time to write a new class. It really should take you no time to write it, since there's little code involved, and if the methods are involved enough to require understanding then this in itself justifies the new class: it can do complicated stuff that's clearly not part of Point.

One clever solution to this would be to make your Pair a wrapper for a Point. That would look something like this:

public class Pair{
  Point p;
  public Pair (int first, int second)
  {
    p = new Point (first, second);
  }

  public int getFirst()
  { 
    return p.getX();
  }
    public int getSecond()
  { 
    return p.getY();
  }
  public int getMember(int index)
  {
    return index==0?p.getX():P/>.getY(); 
    // should do bounds checking 
  }
}



Obviously, this doesn't make a lot of sense for a Pair - why not just use two ints? - but I could imagine a more complex situation where this sort of wrapping would provide a good compromise between the two approaches. This is what you'd do, for example, if you find that you're spending a lot of time manipulating an array or and ArrayList: wrap it in a class and provide just the access you want to, and get the error handling right just once for each access. This gets you out of your own way to some degree, and allows you to get on with writing the actual program instead of spending all of your time getting your data handling right.

Excellent topic, Zel2008. Thanks for posting it.

This post has been edited by jon.kiparsky: 27 January 2012 - 12:04 PM

Was This Post Helpful? 2
  • +
  • -

#4 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2118
  • View blog
  • Posts: 3,244
  • Joined: 21-June 11

Re: Preferences in implementing a pair of integers

Posted 27 January 2012 - 12:07 PM

A generic Pair class will have a runtime penalty compared to a non-generic class for primitive types, because primitives need to be boxed to be used with generics.

However I wouldn't use Point to represent something that isn't a Point because it's counter-intuitive. Sure, leaving a comment helps, but when given the choice between [doing something non-intuitive and explaining it in a comment] and [doing something intuitive that doesn't need a comment], I'd always choose the latter.

So I'd either create a `Pair<T>` class and use `Pair<Integer>`, taking the performance hit (which isn't a big deal for most use cases), or if that's not acceptable create an `IntPair` class.

Depending on your use case, it might make even more sense to create a class specific to your use case where the class name and the variable names tell you what the ints are used for.
Was This Post Helpful? 1
  • +
  • -

#5 jon.kiparsky  Icon User is offline

  • Pancakes!
  • member icon


Reputation: 7807
  • View blog
  • Posts: 13,203
  • Joined: 19-March 11

Re: Preferences in implementing a pair of integers

Posted 27 January 2012 - 12:17 PM

Quote

A generic Pair class will have a runtime penalty compared to a non-generic class for primitive types, because primitives need to be boxed to be used with generics.


Good point. I was speaking of a non-generic, a pair of ints. If you make it generic, there's some overhead, but I don't imagine it would ever be enough to affect your choice.


(I'm guessing that when Adam used the word generic, he was talking about the stock library Point class as opposed to a custom Pair class)
Was This Post Helpful? 0
  • +
  • -

#6 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Re: Preferences in implementing a pair of integers

Posted 27 January 2012 - 12:23 PM

Some very interesting ideas on this so far, I like where these discussions are going. :)

For the sake of throwing another possible solution into the mix, what about something like an AbstractMap.SimpleEntry<Integer,Integer>? You'd get the association between the values without them being mistaken for coordinates, and it seems like intent would be well communicated there -- it's an object that maps one value to
another value.

The only real drawback I can see there is that the key for an AbstractMap.SimpleEntry is not mutable, but there could be ways around that.

Any thoughts on this?
Was This Post Helpful? 0
  • +
  • -

#7 jon.kiparsky  Icon User is offline

  • Pancakes!
  • member icon


Reputation: 7807
  • View blog
  • Posts: 13,203
  • Joined: 19-March 11

Re: Preferences in implementing a pair of integers

Posted 27 January 2012 - 01:02 PM

Now that's a kettle of fish of a different color! That would be useful if you're interested in mapping a function, as long as the function was closed over integers. You'd be limited in the sorts of relationships you could describe - you could have many-to-one but not one-to-many relations. As you say, you'd be well positioned to access pairs by their first value, but you'd lose the ability to access them by any other means. If that's interesting to you, you might want to go ahead and make that a TreeMap, then you'd have them sorted automatically from low to high, which would be useful if you were graphing a function.
Was This Post Helpful? 1
  • +
  • -

#8 SwiftStriker00  Icon User is offline

  • No idea why my code works
  • member icon

Reputation: 433
  • View blog
  • Posts: 1,596
  • Joined: 25-December 08

Re: Preferences in implementing a pair of integers

Posted 27 January 2012 - 08:41 PM

You could always implement the Tuple interface.
Was This Post Helpful? 0
  • +
  • -

#9 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2264
  • View blog
  • Posts: 9,470
  • Joined: 29-May 08

Re: Preferences in implementing a pair of integers

Posted 28 January 2012 - 12:00 PM

View Postjon.kiparsky, on 27 January 2012 - 08:17 PM, said:

(I'm guessing that when Adam used the word generic, he was talking about the stock library Point class as opposed to a custom Pair class)

When I say Generic, it means a class or method that has a Type Specifier, which constrains this particular instance to the specified type. Eg Pair<'T> where 'T is Int is the generic pair class constrained to be int specific. Another example Pair<Sock> is a the generic pair class constrained the be specialized the be Sock specific.
Was This Post Helpful? 0
  • +
  • -

#10 jon.kiparsky  Icon User is offline

  • Pancakes!
  • member icon


Reputation: 7807
  • View blog
  • Posts: 13,203
  • Joined: 19-March 11

Re: Preferences in implementing a pair of integers

Posted 28 January 2012 - 01:42 PM

Oh, okay - nothing to do with the original question, then. Yes, that would be marginally slower, mostly because of the need to box and unbox your ints.

I don't know off hand whether generics impose any inherent time penalty beyond this. That is, I couldn't say whether a Pair<Foo> would be at a disadvantage compared to a PairOfFoo, and if so, by how much. Anyone looked into this?
Was This Post Helpful? 0
  • +
  • -

#11 cfoley  Icon User is online

  • Cabbage
  • member icon

Reputation: 2021
  • View blog
  • Posts: 4,194
  • Joined: 11-December 07

Re: Preferences in implementing a pair of integers

Posted 02 February 2012 - 06:29 PM

A lot of languages have pair and tuple data types built in. A lot of Java programmers roll their own. That's OK to a point but if you're wanting combine two ints in this way, there has to be a concept involved. Why not make that concept your class name. Who knows what methods it will be convenient to place there as your project grows?

Not sold?

private static class ${int a, b;}

// In some method
$ myPair = new $(){{a=5; b=7;}};
System.out.printf("%d %d %n", myPair.a, myPair.B)/>;


Season with good OO practices to taste.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1