简体   繁体   中英

Java how to compare two generic type parameters

The problem is to write generic method, with T constrained to extends Number. Only have a single field variable ArrayList. Have an add method that adds objects to the ArrayList, and then two methods, one that returns the largest in the ArrayList and the other the smallest. My problem is in the largest and smallest methods where I am comparing successive items in the list with each other searching for the largest and smallest, but they are of generic type T and I cannot use < and >, and compareTo() does not work either (I put both errors in the code provided). Can someone take a look and let me know where I am going wrong?

import java.util.ArrayList;

public class MyList<T extends Number> {
   private ArrayList<T> list;
   
   public MyList() {
      list = new ArrayList<T>();
   }
   
   public void add(T obj) {
      list.add(obj);
   }
   
   public T largest() {
      boolean onFirstObj = true;
      T largestVal;
      
      for (int i = 0; i < list.size(); i++) {
         if (onFirstObj) {
            largestVal = list.get(i);
            onFirstObj = false;
         }
         else {
            if (list.get(i) > largestVal) {
               largestVal = list.get(i);
            }
         }
      }
      
      return largestVal;
   }
   
   public T smallest() {
      boolean onFirstObj = true;
      T smallestVal;
      
      for (int i = 0; i < list.size(); i++) {
         if (onFirstObj) {
            smallestVal = list.get(i);
            onFirstObj = false;
         }
         else {
            if (list.get(i).compareTo(smallestVal) < 0) {
               smallestVal = list.get(i);
            }
         }
      }
      
      return smallestVal;
   }
}

The < and > operators can only be used with primitive types, and the Number class does not implement Comparable itself, so you can't use compareTo.

However if you add Comparable<T> as a type bound:

public class MyList<T extends Number & Comparable<T>> {
    ...
}

then you can use the compareTo method:

public T largest() {
    boolean onFirstObj = true;
    T largestVal = null;

    for (T t : list) {
        if (onFirstObj) {
            largestVal = t;
            onFirstObj = false;
        } else {
            if (t.compareTo(largestVal) > 0) {
                largestVal = t;
            }
        }
    }

    return largestVal;
}

You could do it like this.

Number has the methods for accessing primitive values (eg doubleValue()). So you can use doubleValue() for the compare to handle both integer and floating types.

It works because the int, double, float and long methods are declared abstract so any class that extends Number must provide implementations for them. byteValue() and shortValue() are simply methods that call intValue() and are cast appropriately.

As mentioned in the comments, BigInteger and BigDecimal can have precisions that exceed what the doubleValue can accommodate so for those datatypes this solution is destined to fail.

class MyList<T extends Number> {
    private ArrayList<T> list;
    
    public MyList() {
        list = new ArrayList<T>();
    }
    
    public void add(T obj) {
        list.add(obj);
    }
    
    public T largest() {
        T largestVal = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            if (list.get(i).doubleValue() > largestVal.doubleValue()) {
                largestVal = list.get(i);
            }
        }
        return largestVal;
    }
    

    
    public T smallest() {
        T smallestVal = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            if (list.get(i).doubleValue() < smallestVal.doubleValue()) {
                smallestVal = list.get(i);
            }   
        }
        return smallestVal;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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