tags:

views:

118

answers:

5

I want to have a method which calculates the mean of a LinkedList of type Integer, Double and Float.

The problem is the sum += i; statement, since java says that the + operator isn't defined for type Object.

I could do a cast, but if the LinkedList was of type Float, for example, and the cast was to Integer, I would be not computing the correct mean.

What should I do? Thanks.

 public double mean (LinkedList<?> l)
 {
  double sum = 0;
  int n = 0;
  for (Object i : l)
  {
   n++;
   sum += i;
  }

  return sum / n;
 }
+11  A: 

You should restrict your list to Numbers. That is the common superclass for Integer, Float, Double and other numeric types. It has no operators defined, only conversion methods to e.g. double, but that is enough for you here:

 public double mean (LinkedList<? extends Number> l)
 {
  double sum = 0;
  int n = 0;
  for (Number i : l)
  {
   n++;
   sum += i.doubleValue();
  }

  return sum / n;
 }
Péter Török
This whole `<? extends Number>` happened while I was off using Ruby. What is this construct called? Does this syntax `LinkedList<?>` say we have a LL of unknown type, and `LinkedList<? extends Number>` is a LL of unknown types each guaranteed to be subclassed from Number?
Tony Ennis
and why not `LinkedList <Number>` ?
Tony Ennis
To answer your first question: Yes, using `LinkedList<?>` specifies a linked list containing elements of unknown type (they are at least objects) and `LinkedList<? extends Number>` may contain elments of any subtype of Number (and if nobody is doing strange reflection hacks, it gaaranteed). Why not using `LinkedList<Number>`? It ties the users of your api to a specific type. You can't pass in a `LinkedList<Integer>`. In fact there is no need to even required LinkedList, the best way would be to require an `Iterable<? extends Number>`.
Willi
@Tony, this is called a _wildcard with extends_. `LinkedList<? extends Number>` matches any list of a subclass of `Number`. I.e. it can be a `LinkedList<Number>`, a `LinkedList<Integer>`, a `LinkedList<Double>` etc. It is important to note that the latter are _not_ subclasses of `LinkedList<Number>` - that's why the wildcard is needed here.
Péter Török
@Willi, if you want to reflect to someone else's comment, it is recommended to include his nick preceded by a @ in your answer (e.g. @Tony) - otherwise he won't get notified about your comment.
Péter Török
Ah ok, didnt know. Thanks
Willi
@willi @Péter Török Thanks for the info! I'll get to googling on it.
Tony Ennis
A: 
public <T extends Number> double mean (LinkedList<T> l) {
  double sum = 0;
  int n = 0;
  for (T i : l)  {
    n++;
    sum += i.doubleValue();
  }

  return sum / n;
}
in0de
Looks extremely similiar to Peter's answer.
Willi
@Willi: both might be written at same time...
Crozin
in0de
I did, but the only thing you edited is not adding any value to the answer proposed by Peter. Using a generic method with only one parameter is useless.
Willi
In fact, if you see the post time, i posted it before. Actually, 3 minutes before...
in0de
A: 

In Java, generic collections are contravariant. This means that if you have parent class A and class B which extends A, then you cannot make something like List<A> list = new LinkedList<B>();.

But there is a possibility to allow this type of substitution: you can use a construction like List<? extends A> list = new LinkedList<B>();. For your case:

 public double mean (List<? extends Number> l)
 {
  double sum = 0;
  int n = 0;
  for (Object i : l)
  {
   n++;
   sum += i;
  }

  return sum / n;
 }
Roman
Won't compile. The + operator is not defined for objects.
Willi
+1  A: 

The only option would be to generalize on java.lang.Numberbut it wouldn't actually help much as you can't unbox a Number to anything which can be applied to the primitive arithmetic operators. So you'll still have to check for each of the Number-types and call Number.doubleValue, intValue and so forth on the Number-object.

Alexander Sagen
A: 

Here's a couple of things to consider.

  1. Allow Collection instead of only lists
  2. You don't need a separate variable 'n', just use l.size()
  3. Watch out for empty/null input
Bill