简体   繁体   English

简单的Java泛型问题

[英]Simple Java generics question

I want to have a method which calculates the mean of a LinkedList of type Integer, Double and Float. 我想有一种方法来计算Integer,Double和Float类型的LinkedList的平均值。

The problem is the sum += i; 问题是sum += i; statement, since java says that the + operator isn't defined for type Object. 语句,因为java表示没有为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. 我可以进行强制转换,但是例如,如果LinkedList的类型为Float,而强制转换为Integer,则我将无法计算出正确的均值。

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;
 }

You should restrict your list to Number s. 您应将列表限制为Number That is the common superclass for Integer , Float , Double and other numeric types. 这是IntegerFloatDouble和其他数字类型的常见超类。 It has no operators defined, only conversion methods to eg double , but that is enough for you here: 它没有定义运算符,仅将转换方法转换为double ,但这对您来说就足够了:

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

  return sum / n;
 }

The only option would be to generalize on java.lang.Number but it wouldn't actually help much as you can't unbox a Number to anything which can be applied to the primitive arithmetic operators. 唯一的选择是在java.lang.Number上进行泛化,但实际上却无济于事,因为您无法将Number拆箱到可以应用于原始算术运算符的任何内容。 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. 因此,您仍然必须检查每种Number类型,并在Number对象上调用Number.doubleValue,intValue等。

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;
}

In Java, generic collections are contravariant. 在Java中,通用集合是互变的。 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>(); 这意味着,如果您拥有父类A和扩展了A的类B,那么您将无法进行类似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>(); 但是有可能允许这种类型的替换:您可以使用类似List<? extends A> list = new LinkedList<B>();的构造List<? extends A> list = new LinkedList<B>(); 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;
 }

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() 您不需要单独的变量“ n”,只需使用l.size()
  3. Watch out for empty/null input 注意空/空输入

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM