Общий класс пар

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

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

это правильная реализация на этот вопрос ?

public class Pair<firstThing, secondThing>{
   private firstThing first;//first member of pair
   private secondThing second;//second member of pair

   public Pair(firstThing first, secondThing second){
     this.first = first;
     this.second = second;
   }

   public void setFirst(firstThing first){
    this.first = first;
   }

   public void setSecond(secondThing second) {
     this.second = second;
   }

   public thing getFirst() {
     return this.first;
   }

   public thing getSecond() {
     return this.second;
   }
}

14 ответов


почти. Я бы написал это так:

public class Pair<F, S> {
    private F first; //first member of pair
    private S second; //second member of pair

    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    public void setFirst(F first) {
        this.first = first;
    }

    public void setSecond(S second) {
        this.second = second;
    }

    public F getFirst() {
        return first;
    }

    public S getSecond() {
        return second;
    }
}

Edit: я согласен с комментарием @karmakaze. Код должен пропустить сеттеры и сделать первый и второй финал, чтобы сохранить его неизменным.


потребность в классе Пары обычно возникает в более крупных проектах - я собираюсь (повторно)реализовать один для текущего проекта (поскольку предыдущие реализации недоступны).

обычно я делаю его неизменяемым POJO, с функцией удобства для создания экземпляров. Например:

public class Pair<T,U>
{
    public final T first;
    public final U second;
    public static <T,U> Pair<T,U> of(T first, U second);
}

чтобы конечный пользователь мог написать:

return Pair.of (a, b);

и

Pair<A,B> p = someThing ();
doSomething (p.first);
doSomethingElse (p.second);

как упоминалось выше, класс Pair также должен реализовать hashCode (), equals(), необязательно, но полезно toString (), как, возможно, clone() и compareTo () для использования, где они поддерживаются T и U - хотя требуется дополнительная работа для описания того, как эти контракты поддерживаются классом Pair.


вы можете посмотреть на реализацию стандартных классов Java AbstractMap.SimpleEntry и AbstractMap.Simpleimmutable. Это довольно легко для источников google:


вот реализация из Android SDK

/**
 * Container to ease passing around a tuple of two objects. This object provides a sensible
 * implementation of equals(), returning true if equals() is true on each of the contained
 * objects.
 */
public class Pair<F, S> {
    public final F first;
    public final S second;

    /**
     * Constructor for a Pair.
     *
     * @param first the first object in the Pair
     * @param second the second object in the pair
     */
    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    /**
     * Checks the two objects for equality by delegating to their respective
     * {@link Object#equals(Object)} methods.
     *
     * @param o the {@link Pair} to which this one is to be checked for equality
     * @return true if the underlying objects of the Pair are both considered
     *         equal
     */
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Pair)) {
            return false;
        }
        Pair<?, ?> p = (Pair<?, ?>) o;
        return Objects.equal(p.first, first) && Objects.equal(p.second, second);
    }

    /**
     * Compute a hash code using the hash codes of the underlying objects
     *
     * @return a hashcode of the Pair
     */
    @Override
    public int hashCode() {
        return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
    }

    /**
     * Convenience method for creating an appropriately typed pair.
     * @param a the first object in the Pair
     * @param b the second object in the pair
     * @return a Pair that is templatized with the types of a and b
     */
    public static <A, B> Pair <A, B> create(A a, B b) {
        return new Pair<A, B>(a, b);
    }
}

Я думаю, что нет. Цитата:

"класс должен быть настроен более двух типов..."

Я думаю, что они ожидают в отношении :

public class Pair<ThingA, ThingB>

обычно общий тип пары имеет два общие параметры типа, а не один-так что вы могли бы (скажем) a Pair<String, Integer>. Это обычно более полезно, ИМО.

Я бы также предложил вам подумать о более обычном имени для вашего параметра типа, чем "вещь". Например, вы можете использовать Pair<A, B> или Pair<T, U>.


геттеры разбиты

public thing getFirst() {
  return thing.first;
}

public thing getSecond() {
  return thing.second;
}

thing следует заменить на this


после редактирования, он выглядит хорошо.

однако, вы действительно должны реализовать hashCode и equals методы, так что две пары, содержащие одни и те же объекты, будут равны друг другу и могут использоваться в качестве ключей в HashMap. И toString Если вы чувствуете себя щедрым. Эти методы не требуются для выполнения требований, которые вам были даны, но это вещи, которые добавил бы хороший программист.


класс должен быть параметризован над двумя типами один для первого члена и один для второго члена пары.

у вас есть только один параметр.

нужно что-то вроде Pair<F,S> и используйте F, где вы используете thing для первого и S, где thing для второй.


нет. Вы пробовали его кодировать, чтобы посмотреть, работает ли он?

вы, кажется, пропустили эту часть требования:

класс должен быть параметризован над двумя типами один для первого члена и один для второго члена пары.

что означает, что класс, вероятно, должен быть определен как что-то вроде:

public class Pair<T1, T2>

и другие методы обновлены соответственно. (Кстати, я использовал T1 и T2 для см. типы как по соглашению используется короткий - 1 или 2 char-идентификатор).

и

return thing.first;

и

return thing.second;

не будет работать, как в вашем примере, thing - Это тип, а не объект. Подумай о том, что ты хочешь вернуть сюда. Вам даже нужно вызвать метод?

после того, как вы внесли свои изменения, Закодируйте его и напишите модульный тест или простой тестовый жгут, чтобы проверить, работает ли он.


Apache Commons Lang имеет общую реализацию пары

https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html


thing это Переменной Типа в несвойственной нотации-мы обычно используем один верхний регистр (например,T). Затем: переменная типа не имеет методов, поэтому ваши геттеры не будут компилироваться.

быстрое улучшение: замените все thing С T

быстрое исправление для геттеров:

public T getFirst() {
 return first;
}

public T getSecond() {
 return second;
}

одним из требований было разрешить два разных типа для членов пары. Таким образом, подпись класса должна выглядеть так:

public Pair<S,T> {
  private S first;
  private T second;
  //...
}

моя версия пары. Это также обрабатывает сравнения. PS: большая часть кода взята из AOSP.

package util;

import java.util.Objects;

public class Pair<F extends Comparable<F>, S extends Comparable<S>>
  implements Comparable<Pair<F, S>> {

    public final F first;
    public final S second;

    /**
     * Constructor for a Pair.
     *
     * @param first  the first object in the Pair
     * @param second the second object in the pair
     */
    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    /**
     * Checks the two objects for equality by delegating to their respective
     * {@link Object#equals(Object)} methods.
     *
     * @param o the {@link Pair} to which this one is to be checked for equality
     * @return true if the underlying objects of the Pair are both considered
     * equal
     */
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Pair)) {
            return false;
        }
        Pair<?, ?> p = (Pair<?, ?>) o;
        return Objects.equals(p.first, first) && Objects.equals(p.second, second);
    }

    /**
     * Compute a hash code using the hash codes of the underlying objects
     *
     * @return a hashcode of the Pair
     */
    @Override
    public int hashCode() {
        return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
    }

    /**
     * Convenience method for creating an appropriately typed pair.
     *
     * @param a the first object in the Pair
     * @param b the second object in the pair
     * @return a Pair that is templatized with the types of a and b
     */
    public static <A extends Comparable<A>, B extends Comparable<B>> Pair<A, B> create(A a, B b) {
        return new Pair<>(a, b);
    }

    @Override
    public int compareTo(Pair<F, S> that) {
        int cmp = this.first.compareTo(that.first);
        if (cmp == 0)
            cmp = this.second.compareTo(that.second);
        return cmp;
    }
}

я реализовал что-то подобное, но со статическим строителем и цепными сеттерами

public class Pair<R, L> {

private R left;
private L right;

public static <K,V> Pair<K, V> of(K k, V v) {
    return new Pair<K,V>(k, v);
}

public Pair() {}

public Pair(R key, L value) {
    this.left(key);
    this.right(value);
}

public R left() {
    return left;
}

public Pair<R, L> left(R key) {
    this.left = key;
    return this;
}

public L right() {
    return right;
}

public Pair<R, L> right(L value) {
    this.right = value;
    return this;
}
}