以元组为键的Java映射,按元组键删除/获取

以元组为键的Java映射,按元组键删除/获取,java,treemap,Java,Treemap,我有一个场景,我希望有一个以元组为键的排序映射: var scheduledRunnables = new TreeMap<Tuple<Integer, String>, Runnable>(Comparator.comparing(Tuple::getKey)); Tuple类只是一个如下所示的数据持有者: scheduledRunnables.put(new Tuple<>(1, "Some task"), () -> System.out.pri

我有一个场景,我希望有一个以元组为键的排序映射:

var scheduledRunnables = new TreeMap<Tuple<Integer, String>, Runnable>(Comparator.comparing(Tuple::getKey));
Tuple
类只是一个如下所示的数据持有者:

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
@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;
    }

}
var scheduledRunnables = new TreeMap<Tuple<Integer, String>, Runnable>();
@数据
公共类元组{
私钥;
私人价值;
公共元组(K键,V值){
this.key=key;
这个值=值;
}
}

这将如何实施?无需定制SortedMap接口的实现,是否可行?有没有更好的方法来实现我的目标?

你可以让你的
不相关(这只是一个元信息)。因此,初始化类(可选参数)时不需要它,在使用
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);
    }
}
然后,您可以通过以下方式调用get:

Runnable runnable = scheduledRunnables.get(new Tuple<>(1));
Runnable-Runnable=scheduledRunnables.get(新元组(1));
调用
get
时,我只想提供订单整数

它有一些隐藏的假设,这些假设不是由您的代码强制执行的。如果您使用一个元组作为键,那么仅通过该元组的一部分从映射中获取一个条目就有可能返回多个条目。举个例子,考虑这个简化的代码:

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?
Map Map=newtreemap();
put(新元组(1,“Foo”),“First”);
map.put(新元组(1,“Bar”),“Second”);
? = map.get(1);//这种回报应该是什么?
如果只关心元组的一部分,那么
get()
,应该返回多个值


如果您不关心元组的一部分,那么就不应该使用元组作为映射的键,因为键应该是不同的,但键的一部分不是。在不了解更多用例的情况下,我不确定什么是最适合您的选项。

老实说,只需维护两个映射即可

Map<Integer, Runnable> idToRunnable;
Map<Integer, String> idToName;
Map-idToRunnable;
地图idToName;
或者将元组用作值而不是键:

Map<Integer, Tuple<String, Runnable>>
Map

非常简单,准确地解决了我的用例,非常感谢!这令人困惑。在整数为1的映射中可能有多个可运行项,您可以任意获得其中一个。这是对映射的滥用。@Michael这取决于,真的,如果
taskName
只是一个元值(就像我假设的那样),那么在我看来,这是对
TreeMap
的完全有效的使用,而不是使用元组。使用
Task
@Michael这只是一个命名问题,我只是使用了OPs问题中的一个,但可能
Task
更适合这种情况。我假设这将返回“Second”,因为字符串值是元数据,不重要,再次添加1将覆盖第一个值。但是我完全同意你的最后一点,我可能会重新考虑。关于你的编辑,我希望世界元组覆盖hello元组。或者
Map
。这是迄今为止最简单的解决方案,谢谢你,因为我认为OP正在学习。关于
Tuple
要求,我也有一些疑问,但很好。@davidxxx很公平。我个人永远不会使用
元组
,可能除了一些中间流操作之外,在这些操作中定义特定的数据持有者类是一件非常麻烦的事情,但我在这里并不完全反对它。
Map<Integer, Tuple<String, Runnable>>