Как найти минимальное значение из универсального массива?

У меня возникли проблемы с попыткой написать метод для возврата объекта с наименьшим объемом в универсальном списке ArrayList. Вот рекомендации, которые мне дали для написания кода:

min () — этот метод принимает ArrayList ограниченного универсального типа, который допускает только объекты Shape и их подклассы. - Метод должен возвращать объект с минимальным объемом из списка объектов.

Но я не совсем уверен, правильно ли я его выполнил. Есть ли способ использовать Collections.min (и Collections.max, так как мне тоже нужно написать метод максимального объема)? Я получаю связанную ошибку несоответствия, говорящую: универсальный метод min(Collection) типа Collections неприменим для аргументов (ArrayList). Выведенный тип Shape не является допустимой заменой ограниченного параметра >

Мой класс Shape — это просто интерфейс с функцией getVolume(); метод, в котором другие мои классы (сферы, эллипсоиды и т. д.) переопределяют этот метод:

public interface Shape {
    public double getVolume();
}

И вот мой метод min (в другом классе с другими методами), с которым у меня проблемы:

public static <T> T  min() {
    ArrayList<? extends Shape> list;    

     T min = Collections.min(list));
        return min;

person user3376836    schedule 17.04.2014    source источник
comment
Ваш интерфейс Shape должен расширять Comparable‹Shape›, или вы должны передать Comparator‹Shape› в Collections.min() (это было бы моим предпочтительным решением).   -  person JB Nizet    schedule 17.04.2014
comment
Проголосовал за ваш комментарий, вы правы, но если это невозможно, вам все равно нужно реализовать какой-то метод compareTo(). вот документ для сопоставимого docs.oracle.com/javase /7/docs/api/java/lang/Comparable.html   -  person Justin Mitchell    schedule 17.04.2014


Ответы (4)


Это связано с тем, что Java стирает тип во время выполнения, поэтому Коллекция не знает, с каким типом она на самом деле имеет дело. Это ограничивающий фактор при использовании дженериков Java - я сталкивался с ним несколько лет назад, но не мог найти способ обойти это, и это оказалось языковым ограничением.

Лучше всего создать метод public T getMinVolume(ArrayList<T> list) для перебора каждого T.

eg.

public T getMinVolume(ArrayList<T> list) {
    T min = null;
    for(T item: list) {
        if (min == null) {
            min = item;
        }

        if (min > item) {
            min = item;
        }
    }

    return min;
}

Как-то так, моя Ява немного подзабыла, но логика должна работать.

person Justin Mitchell    schedule 17.04.2014

Чтобы сравнить объемы, вы можете сделать Shape Comparable или использовать Comparator.

Сопоставимые

Это требует изменений во всех фигурах, но не в коде, который их использует. Я использовал абстрактный класс, чтобы легко сравнивать все классы.

public interface Shape extends Comparable<Shape> {
    public double getVolume();
}

public abstract class BaseShape implements Shape {
    public int compareTo(Shape other) {
        return Double.compare(getVolume(), other.getVolume());
    }
} 

public class Box extends BaseShape {
    public double getVolume() {
        return volume;
    } 
} 
public class Ball extends BaseShape { /* ... */ } 

И использовать:

Collections.min(collection);

Компаратор

Это не требует модификации фигур, но немного больше кода для их использования.

public class ShapeComparator implements Comparator<Shape> {
    public int compare(Shape a, Shape b) {
        return Double.compare(a.getVolume(), b.getVolume());
    } 
} 

И использовать:

Collections.min(collection, new ShapeComparator());
person PurkkaKoodari    schedule 17.04.2014

В java.utils.Collections есть два варианта.

  • static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
  • static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)

Первый из них требует, чтобы ваша форма реализовывала Comparator<Shape>

class Shape implements Comparable<Shape> {
    int compareTo(Shape other) {
       return Math.signum(getVolume()-other.getVolume);
    }
    ...
}

ArrayList<Shape> myShapes = ...
Shape minShape = Collections.min(myShapes);

Второй требует, чтобы вы создали собственный компаратор:

class Shape {
    ...
}

class ShapeVolumeComparator implements Comparator<Shape> {
    int compare(Shape s1, Shapes2) {
       return Math.signum(s1.getVolume()-s2.getVolume());
    }
}

ArrayList<Shape> myShapes = ...;
Shape minShape = Collections.min(myShapes, new ShapeVolumeComparator() );

В первом меньше кода, но второй более адаптируемый, если вы хотите отсортировать что-то еще, например, площадь поверхности или положение.

person Michael Anderson    schedule 17.04.2014

Вы должны использовать этот метод http://www.tutorialspoint.com/java/util/collections_min_comparator.htm и укажите компаратор:

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;

public abstract class Shape {
    public abstract double getVolume();

    public Shape min(Collection<? extends Shape> col) {
        return Collections.min(col, new Comparator<Shape> () {
            public int compare(Shape l, Shape r) {
                return ((Double) l.getVolume()).compareTo(r.getVolume());
            }
        });
    }
}
person Luc DUZAN    schedule 17.04.2014