954,518 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

One method for stack of either Integer or Double parameters

Hi All,

I am just learning Java and there is a concept that I cannot grasp. I am writing a simple exercise program that works with stacks. I have a sum method for two different types - Integer and Double. They both have the same logic, so it seems redundant to do it this way. I thought it would be possible to write one method that takes either type. So I have read about generics and still cannot figure out a solution. Is it at all possible?

Here are my add methods:

// Return the sum of the stack
  public static Integer sum (Stack<Integer> stack) {
    Integer sum = 0, current;
    Stack<Integer> temp = new Stack<Integer>(); 
    
    // calculate the sum
    while (!stack.empty() ) { 
      current = stack.pop();
      sum = sum + current;
      temp.push(current);
    }
    
    // rebuild the stack
    while (!temp.empty()) { 
      stack.push(temp.pop());
    }
    
    return sum;
  }
  
  // Return the sum of the stack
  public static Double sum (Stack<Double> stack) {
    Double sum = 0.0, current;
    Stack<Double> temp = new Stack<Double>(); 
    
    // calculate the sum
    while (!stack.empty() ) { 
      current = stack.pop();
      sum = sum + current;
      temp.push(current);
    }
    
    // rebuild the stack
    while (!temp.empty()) { 
      stack.push(temp.pop());
    }
    
    return sum;
  }
osjak
Newbie Poster
10 posts since Mar 2008
Reputation Points: 10
Solved Threads: 0
 

Both the Integer and Double objects extend Number. So you could do the following:

public static Number sum (Stack<Number> stack) {


Note that this method will require you to check if the numbers are Integers or Doubles.

Also, remember that you can't use the + operation to add objects.

darkagn
Veteran Poster
1,197 posts since Aug 2007
Reputation Points: 404
Solved Threads: 200
 

If you want to do this Generically, consider this code as an example:

public class GenericNumbers<T>{

	private T number;
	private ArrayList<T> numbers = new ArrayList<T>();
	
	public GenericNumbers(){	
	}
}


If that does not make sense to you, read the two lectures on Generics found here (they are easy to understand): http://www.cs.umbc.edu/courses/undergraduate/202/spring09/MiscPages/schedule.shtml

BestJewSinceJC
Posting Maven
2,772 posts since Sep 2008
Reputation Points: 874
Solved Threads: 354
 

Why create a new stack in these methods. Just iterate thru the stack and add the elements?

int sum = 0;
for (int i: stack) {
  sum += i;
}
JamesCherrill
Posting Genius
Moderator
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
 

Here part of a possible solution.. the following compiles OK

public <T> T sum(Stack<T> stack) {
	T sum;  // really want to say    T sum= 0;
	for (T num : stack){
		// can't do this:  sum += num;
	}
	return sum;
}


ie, that's how you declare a method to take a Stack of Somethings, and return a Something result. What I can't figure out is how to do arithmetic on the Somethings. You can declare as , which is closer to the right spirit, but still doesn't get you any arithmetic capabilities. Ideas anyone?

JamesCherrill
Posting Genius
Moderator
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
 

It does get you arithmetic capabilities from within another class where you instantiate an Object of that generic class.

BestJewSinceJC
Posting Maven
2,772 posts since Sep 2008
Reputation Points: 874
Solved Threads: 354
 

Hi BJSJC. What I mean is that with a variable defined as generic type all you can access at compile time are the methods defined on Number itself, which do not seem to include any arithmetic functions. Do you know of another class that we could use to restrict so that it includes Integer and Double and also gives arithmetic?
James

JamesCherrill
Posting Genius
Moderator
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
 

With the class you have defined, you can use something like. .

public int addInteger(){
		int result = 0; 
		for (T i: numbers){
			Integer j = (Integer)i;
			result+=j;
		}
		
		return result;
	}


This is where 'numbers' is defined as an ArrayList.

BestJewSinceJC
Posting Maven
2,772 posts since Sep 2008
Reputation Points: 874
Solved Threads: 354
 

Yes, you can do that, but what when you want to return a value of type T? If you define the result as Integer, that's OK, you can then do the same thing for Double, that's OK too, now you have overloaded methods that will work, but that's not what the OP was asking.

You can try this

public <T extends Number> T sum(Stack<T> stack) {
	Integer sum = 0;
	for (T num : stack){
		Integer n = (Integer) num;
		sum += n;
	}
	return (T) sum;
}


and hope that if happens to be Double then the value won't overflow, or do the same thing with Double temp variables, and hope there's no rounding problems, and no runtime cast errors...

JamesCherrill
Posting Genius
Moderator
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
 

What you want to do does not make sense then. You wouldn't expect the ArrayList class, which is generic, to add up all of the numbers in the array for you. The purpose is to provide a container, not to have specific implementations.

BestJewSinceJC
Posting Maven
2,772 posts since Sep 2008
Reputation Points: 874
Solved Threads: 354
 

Sorry, obvious misunderstanding here. The method does the addition, or tries to, but is stymied by the problem of doing arithmetic on generic types.The ArrayList bit is almost irrelevant. The quest is to write a method that takes a generic parameter type, performs some arithmetic on it, and returns a result of the same type. Sure you can write n overloaded methods, but to OP wanted to know if there was a single method solution using generics. (ps, I don't think there is).
J

JamesCherrill
Posting Genius
Moderator
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
 

BestJewSinceJC, thank you for the lectures. I will sure read them.

JamesCherrill, thank you for your version of the code. I didn't know the extended for loop is applicable to stacks and queues, that will clean up my code. Regarding your proposed solution - it almost works. It works fine with Integers the way you posted it, however it gives a runtime error if I pass a Double to it:
java.lang.Double cannot be cast to java.lang.Integer.
May be I didn't exactly understand you comments? In any case, thank you for helping!

osjak
Newbie Poster
10 posts since Mar 2008
Reputation Points: 10
Solved Threads: 0
 

You can write an equivalent method that takes an array of Doubles. James' comment was making the point that by doing so, you are not really writing "generic" code. Generic code should provide methods that can work for any type of Object. Hence, it is "generic". If you read the lectures you'll gain a better understanding of what I'm talking about.

BestJewSinceJC
Posting Maven
2,772 posts since Sep 2008
Reputation Points: 874
Solved Threads: 354
 
I didn't know the extended for loop is applicable to stacks and queues

Yes, it works for everything that implements the Collection interface. In fact the code I posted can have the parameter as Collection rather than Stack and will then be more widely useful.Regarding your proposed solution - it almost works. It works fine with Integers the way you posted it, however it gives a runtime error if I pass a Double to it:
That's right - as I said "hope there's... no runtime cast errors" and after a bit more thought I'm even more convinced there is no sensible way to do what you ask. The only polymorphic way to do addition is via the + operator, that only works on primitives (int, double etc), but generics can only be reference types (Integer, Float etc)

JamesCherrill
Posting Genius
Moderator
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
 
That's right - as I said "hope there's... no runtime cast errors" and after a bit more thought I'm even more convinced there is no sensible way to do what you ask. The only polymorphic way to do addition is via the + operator, that only works on primitives (int, double etc), but generics can only be reference types (Integer, Float etc)

I think that if you use Number class instead of T, you can call methods such as doubleValue() and intValue(), then use the + operator and finally return either an Integer or Double. Number is an abstract class that both of these classes extend, so the true polymorphic method of doing what is required would be to use a Stack and return Number.

darkagn
Veteran Poster
1,197 posts since Aug 2007
Reputation Points: 404
Solved Threads: 200
 

Hi Darkagn
Problem here is that Number is an abstract class, so you would have to chose a subclass (eg Integer) to instantiate a value to return. Number only has the xxxValue() methods, so you can't do much with it unles you know what subclass it really is. If the original data is Double, you need to calculate & return Double, ditto Integer, and there's no way I know to do that without explicitly coding both those cases - unless you have a better idea???
J

JamesCherrill
Posting Genius
Moderator
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
 

So in Java you can't declare that you will return an object of type Number, but actually return an Integer or Double (since they are subclasses)? Is that correct?

darkagn
Veteran Poster
1,197 posts since Aug 2007
Reputation Points: 404
Solved Threads: 200
 

No, that is not correct. You can return any subclass of Number if the return type is declared as Number. But the point made earlier still stands.

BestJewSinceJC
Posting Maven
2,772 posts since Sep 2008
Reputation Points: 874
Solved Threads: 354
 
No, that is not correct. You can return any subclass of Number if the return type is declared as Number.


If that is the case then I think my logic should work. If the method signature was like this:

public Number stackSum(Stack<Number> numbers)

Then I think it should be possible to have one method for both Integer and Double objects.

darkagn
Veteran Poster
1,197 posts since Aug 2007
Reputation Points: 404
Solved Threads: 200
 

It is possible, but first, you have to verify the Object's type, then cast it. That isn't Generic code.

BestJewSinceJC
Posting Maven
2,772 posts since Sep 2008
Reputation Points: 874
Solved Threads: 354
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You