1

Following code is a part of a project in which I need to determine the minimum/maximum of datacolumns. The problem is, I don't know whether the column will contain floats or ints. My attempt at making a generic class to do this is the following but this gives me the error on currentVal > compareVal. My question is; where do I go wrong?

 public <T> List<DataRow> compare(boolean Int) {
    for(int i = 0; i<table.getRowCount(); i++){
        T currentVal = (T) argument.resolve(row).getValue();
        DataRow compare = table.getRow(i);
        T compareVal = (T) argument.resolve(compare).getValue();
        // if there's a new minimum or there's a new maximum
        if((currentVal > compareVal && minimum) || (currentVal < compareVal && maximum)){
            row = compare;
            rowlist.clear();
            rowlist.add(compare);
        }
        // if there's a duplicate minimum/maximum
        else if(currentVal == compareVal)
            rowlist.add(compare);
    }
    return rowlist;
}

by the way, in the first if statement, minimum and maximum are booleans which are true either if a minimum or maximum is to be calculated.

This is supposed to be an alternative to my current method(s);

public List<DataRow> floatCompare() {
    for(int i = 0; i<table.getRowCount(); i++){
        float currentVal = (float) argument.resolve(row).getValue();
        DataRow compare = table.getRow(i);
        float compareVal = (float) argument.resolve(compare).getValue();
        // if there's a new minimum or there's a new maximum
        if((currentVal > compareVal && minimum) || (currentVal < compareVal && maximum)){
            row = compare;
            rowlist.clear();
            rowlist.add(compare);
        }
        // if there's a duplicate minimum/maximum
        else if(currentVal == compareVal)
            rowlist.add(compare);
    }
    return rowlist;
}
public List<DataRow> intCompare() {
    for(int i = 0; i<table.getRowCount(); i++){
        int currentVal = (int) argument.resolve(row).getValue();
        DataRow compare = table.getRow(i);
        int compareVal = (int) argument.resolve(compare).getValue();
        // new minimum or new maximum
        if((currentVal > compareVal && minimum) || (currentVal < compareVal && maximum)){
            row = compare;
            rowlist.clear();
            rowlist.add(compare);
        }
        // duplicate minimum/maximum
        else if(currentVal == compareVal)
            rowlist.add(compare);
    }
    return rowlist;
}

These functions work, but I want to combine them into a generic class because they both do exactly the same thing.

logos
  • 61
  • 1
  • 8
  • 1
    Are they really int/float or are they Integer/Float? What does argument.resolve(row).getValue() return? Where does this variable come from? – Necreaux May 13 '15 at 18:21
  • Your code does not compile, could you fix it? – igreenfield May 13 '15 at 18:21
  • I know it doesn't compile, sorry. It runs on a huge back-end containing the structure of the datarows and columns. argument.resolve(row).getValue() returns a value which is either a float or an int. Never and Integer – logos May 13 '15 at 18:25
  • Reduce the problem to a [minimal example](http://stackoverflow.com/help/mcve) which shows what you need to do. As it stands, we don't have enough information to give you accurate suggestions. – Radiodef May 13 '15 at 18:26
  • Why does it matter that they are floats or int's? Wouldn't you compare them the same way? – chancea May 13 '15 at 18:27
  • That's exactly the point. the problem is, I can't assign them to variables if I don't know it's going to be either an int or float. – logos May 13 '15 at 18:28

2 Answers2

2

We can do comparisons generically through the Comparable interface.

Returns:

a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

E.g.:

static <T extends Comparable<? super T>> T min(T lhs, T rhs) {
    // same as ( (lhs < rhs) ? lhs : rhs )
    return (lhs.compareTo(rhs) < 0) ? lhs : rhs;
}

Both Float and Integer implement Comparable.

A line-for-line copy of your code using Comparable would be:

public List<DataRow> compare(boolean Int) {
    for(int i = 0; i<table.getRowCount(); i++){
        Comparable currentVal = (Comparable) argument.resolve(row).getValue();
        DataRow compare = table.getRow(i);
        Comparable compareVal = (Comparable) argument.resolve(compare).getValue();
        // if there's a new minimum or there's a new maximum
        int comparison = currentVal.compareTo(compareVal);
        if((comparison > 0 && minimum) || (comparison < 0 && maximum)){
            row = compare;
            rowlist.clear();
            rowlist.add(compare);
        }
        // if there's a duplicate minimum/maximum
        else if(comparison == 0)
            rowlist.add(compare);
    }
    return rowlist;
}

But you will get warnings from using raw types. It's not clear enough to me what your code is supposed to do for me to say whether this is an accurate conversion and how to avoid using the raw types.

Otherwise, there is no way to do arithmetic generically.

Community
  • 1
  • 1
Radiodef
  • 37,180
  • 14
  • 90
  • 125
  • 1
    Wow, your line-for-line copy was exactly what I needed. Despite my poor explanation you managed to fix it, I'd give you a thousand upvotes if I could. – logos May 13 '15 at 20:24
  • 1
    However, definitely read the Q&A I linked to on raw types. Consider refactoring it in a way that lets you not use them. (But a raw Comparable isn't as bad as some other raw types: the declaration of compareTo should make it throw an exception immediately instead of allowing heap pollution. The collections framework uses raw Comparables routinely behind the scenes...) – Radiodef May 13 '15 at 20:29
1

In Java, generics are only used at compile-time to help assure type correctness. For your purposes, I suggest that you make two functions: One for ints and one for floats

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80