Карта Java с ключом кортежа, удаление / получение ключом кортежа - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть сценарий, в котором я хотел бы иметь отсортированную карту с кортежем в качестве ключа:

var scheduledRunnables = new TreeMap<Tuple<Integer, String>, Runnable>(Comparator.comparing(Tuple::getKey));

При добавлении я хочу добавить кортеж:

scheduledRunnables.put(new Tuple<>(order, taskName), task);

Когдасортировка, я хочу, чтобы это было отсортировано по целому порядку, так как это определяет порядок выполнения исполняемых файлов.Я не обязательно знаю значение переменной taskName.При вызове get я хочу указать только целое число заказа по той же причине, что и ранее.При звонке put я хочу принять во внимание всю пару.Итак, что-то вроде этого:

scheduledRunnables.put(new Tuple<>(1, "Some task"), () -> System.out.println("asdf"));
scheduledRunnables.get(1).run(); // Should output 'asdf'
scheduledRunnables.put(new Tuple<>(1, "Some task"), () -> System.out.println("qwerty"));
scheduledRunnables.get(1).run(); // Should output 'qwerty'
scheduledRunnables.remove(1).run(); // Should output 'qwerty' and remove from map

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

@Data
public class Tuple<K, V> {

    private final K key;
    private V value;

    public Tuple(K key, V value) {
        this.key = key;
        this.value = value;
    }

}

Как это будет реализовано?Возможно ли это сделать без специальной реализации интерфейса SortedMap?Есть ли лучший способ добиться того, чего я добиваюсь?

Ответы [ 3 ]

0 голосов
/ 20 февраля 2019

При вызове get я хочу указать только целое число заказа

, в котором есть некоторые скрытые предположения, которые не применяются вашим кодом.Если вы используете Tuple в качестве ключа, то получение записи из карты только одной частью этого Tuple имеет возможность вернуть несколько записей.В качестве примера рассмотрим этот упрощенный код:

Map<Tuple<Integer, String>, String> map = new TreeMap<>();
map.put(new Tuple<>(1, "Foo"), "First");
map.put(new Tuple<>(1, "Bar"), "Second");

? = map.get(1); // What should this return?

То, что get(), если вы заботитесь только о части кортежа, должно возвращать несколько значений.

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

0 голосов
/ 20 февраля 2019

Честно, просто поддерживай две карты.

Map<Integer, Runnable> idToRunnable;
Map<Integer, String> idToName;

Или используйте кортеж для значения вместо ключа:

Map<Integer, Tuple<String, Runnable>>
0 голосов
/ 20 февраля 2019

Вы можете просто сделать вас value неактуальным (это просто метаинформация).Поэтому он не нужен для инициализации класса (необязательный параметр) и не учитывается при использовании hashCode или equals:

public class Tuple<K extends Comparable<K>, V> implements Comparable<Tuple<K, V>> {
    private final K key;
    private V value;

    public Tuple(K key) {
        this.key = key;
    }

    public Tuple(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public int hashCode() {
        return key.hashCode();
    }

    public boolean equals(Object obj) {
        return obj == this || (obj instanceof Tuple) && key.equals(((Tuple) obj).key);
    }

    public int compareTo(Tuple<K, V> other) {
        return key.compareTo(other.key);
    }
}

Я также сделал сопоставимым Tuple, который будет просто сравниватьключи, так что вы можете создать свой TreeMap без пользовательских Comparator, как это:

var scheduledRunnables = new TreeMap<Tuple<Integer, String>, Runnable>();

Затем вы можете вызвать ваш получить с:

Runnable runnable = scheduledRunnables.get(new Tuple<>(1));
...