This should work in one pass and return appropriate null
if no second highest value is available in the data and making no assumptions about the values in the input data:
static <T extends Comparable> T find2ndMax(List<T> data) {
if (null == data || data.size() < 2) {
return null;
}
T max1 = data.get(0).compareTo(data.get(1)) > 0 ? data.get(0) : data.get(1);
T max2 = data.get(0).compareTo(data.get(1)) < 0 ? data.get(0) : data.get(1);
for (int i = 2, n = data.size(); i < n; i++) {
T x = data.get(i);
if (x.compareTo(max1) > 0) {
max2 = max1;
max1 = x;
} else if (x.compareTo(max2) > 0) {
max2 = x;
}
}
return max2;
}
Tests (comparing to the fixed method of the accepted answer):
List<List<Float>> tests = Arrays.asList(
null,
Collections.emptyList(),
Arrays.asList(-1f),
Arrays.asList(-1f, -2f),
Arrays.asList(-1f, 1f),
Arrays.asList(-1f, -2f, 3f),
Arrays.asList(-1f, 4f, -2f, 2f)
);
for (List<Float> t : tests) {
System.out.print("2nd max in " + t + ": ");
System.out.print("find2Max() = " + find2ndMax(t) + "; secondHighest() = " );
try {
System.out.print(secondHighest(t));
} catch(Exception ex) {
System.out.print("FAIL: " + ex.getMessage());
}
System.out.println();
}
Output
2nd max in null: find2Max() = null; secondHighest() = FAIL: null
2nd max in []: find2Max() = null; secondHighest() = 0.0
2nd max in [-1.0]: find2Max() = null; secondHighest() = 0.0
2nd max in [-1.0, -2.0]: find2Max() = -2.0; secondHighest() = 0.0
2nd max in [-1.0, 1.0]: find2Max() = -1.0; secondHighest() = 0.0
2nd max in [-1.0, -2.0, 3.0]: find2Max() = -1.0; secondHighest() = 0.0
2nd max in [-1.0, 4.0, -2.0, 2.0]: find2Max() = 2.0; secondHighest() = 2.0