简体   繁体   English

Java - 如何创建新条目(键、值)

[英]Java - How to create new Entry (key, value)

I'd like to create new item that similarly to Util.Map.Entry that will contain the structure key , value .我想创建类似于Util.Map.Entry新项目,它将包含结构keyvalue

The problem is that I can't instantiate a Map.Entry because it's an interface.问题是我无法实例化Map.Entry因为它是一个接口。

Does anyone know how to create a new generic key/value object for Map.Entry?有谁知道如何为 Map.Entry 创建一个新的通用键/值对象?

There's public static class AbstractMap.SimpleEntry<K,V> .public static class AbstractMap.SimpleEntry<K,V> Don't let the Abstract part of the name mislead you: it is in fact NOT an abstract class (but its top-level AbstractMap is).不要让名称的Abstract部分误导您:它实际上不是一个abstract类(但它的顶级AbstractMap是)。

The fact that it's a static nested class means that you DON'T need an enclosing AbstractMap instance to instantiate it, so something like this compiles fine:这是一个事实static嵌套类意味着你不需要一个封闭AbstractMap实例来实例化,所以像这样的编译罚款:

Map.Entry<String,Integer> entry =
    new AbstractMap.SimpleEntry<String, Integer>("exmpleString", 42);

As noted in another answer, Guava also has a convenient static factory method Maps.immutableEntry that you can use.正如另一个答案中所述,Guava 还有一个方便的static工厂方法Maps.immutableEntry您使用。


You said:你说:

I can't use Map.Entry itself because apparently it's a read-only object that I can't instantiate new instanceof我不能使用Map.Entry本身,因为显然它是一个只读对象,我无法实例化新的instanceof

That's not entirely accurate.这并不完全准确。 The reason why you can't instantiate it directly (ie with new ) is because it's an interface Map.Entry .不能直接(即使用new )实例化它的原因是因为它是一个interface Map.Entry


Caveat and tip警告和提示

As noted in the documentation, AbstractMap.SimpleEntry is @since 1.6 , so if you're stuck to 5.0, then it's not available to you.如文档中所述, AbstractMap.SimpleEntry@since 1.6 ,因此如果您坚持使用 5.0,那么您将无法使用它。

To look for another known class that implements Map.Entry , you can in fact go directly to the javadoc.要查找另一个implements Map.Entry已知类,您实际上可以直接转到 javadoc。 From the Java 6 versionJava 6 版本开始

Interface Map.Entry接口映射.Entry

All Known Implementing Classes :所有已知的实现类

Unfortunately the 1.5 version does not list any known implementing class that you can use, so you may have be stuck with implementing your own.不幸的是, 1.5 版本没有列出您可以使用的任何已知实现类,因此您可能一直在实现自己的类。

Starting from Java 9, there is a new utility method allowing to create an immutable entry which is Map#entry(Object, Object) .Java 9开始有一个新的实用程序方法允许创建一个不可变的条目Map#entry(Object, Object)

Here is a simple example:这是一个简单的例子:

Entry<String, String> entry = Map.entry("foo", "bar");

As it is immutable, calling setValue will throw an UnsupportedOperationException .由于它是不可变的,调用setValue将抛出UnsupportedOperationException The other limitations are the fact that it is not serializable and null as key or value is forbidden, if it is not acceptable for you, you will need to use AbstractMap.SimpleImmutableEntry or AbstractMap.SimpleEntry instead.其他限制是它不可序列化并且禁止作为键或值使用null ,如果您不能接受,则需要使用AbstractMap.SimpleImmutableEntryAbstractMap.SimpleEntry代替。

NB: If your need is to create directly a Map with 0 to up to 10 (key, value) pairs, you can instead use the methods of type Map.of(K key1, V value1, ...) .注意:如果您需要直接创建一个包含 0 到最多 10 个(键,值)对的Map ,您可以改用Map.of(K key1, V value1, ...)类型的方法。

You can just implement the Map.Entry<K, V> interface yourself:你可以自己实现Map.Entry<K, V>接口:

import java.util.Map;

final class MyEntry<K, V> implements Map.Entry<K, V> {
    private final K key;
    private V value;

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

    @Override
    public K getKey() {
        return key;
    }

    @Override
    public V getValue() {
        return value;
    }

    @Override
    public V setValue(V value) {
        V old = this.value;
        this.value = value;
        return old;
    }
}

And then use it:然后使用它:

Map.Entry<String, Object> entry = new MyEntry<String, Object>("Hello", 123);
System.out.println(entry.getKey());
System.out.println(entry.getValue());

Try Maps.immutableEntry from Guava尝试来自Guava 的Maps.immutableEntry

This has the advantage of being compatible with Java 5 (unlike AbstractMap.SimpleEntry which requires Java 6.)这具有与 Java 5 兼容的优点(与需要 Java 6 的AbstractMap.SimpleEntry不同。)

Example of AbstractMap.SimpleEntry: AbstractMap.SimpleEntry 的示例:

import java.util.Map; 
import java.util.AbstractMap;
import java.util.AbstractMap.SimpleEntry;

Instantiate:实例化:

ArrayList<Map.Entry<Integer, Integer>> arr = 
    new ArrayList<Map.Entry<Integer, Integer>>();

Add rows:添加行:

arr.add(new AbstractMap.SimpleEntry(2, 3));
arr.add(new AbstractMap.SimpleEntry(20, 30));
arr.add(new AbstractMap.SimpleEntry(2, 4));

Fetch rows:获取行:

System.out.println(arr.get(0).getKey());
System.out.println(arr.get(0).getValue());
System.out.println(arr.get(1).getKey());
System.out.println(arr.get(1).getValue());
System.out.println(arr.get(2).getKey());
System.out.println(arr.get(2).getValue());

Should print:应该打印:

2
3
20
30
2
4

It's good for defining edges of graph structures.它适用于定义图结构的边。 Like the ones between neurons in your head.就像大脑中神经元之间的那些。

您实际上可以使用: Map.Entry<String, String> en= Maps.immutableEntry(key, value);

Why Map.Entry ?为什么是Map.Entry I guess something like a key-value pair is fit for the case.我想像键值对这样的东西适合这种情况。

Use java.util.AbstractMap.SimpleImmutableEntry or java.util.AbstractMap.SimpleEntry使用java.util.AbstractMap.SimpleImmutableEntryjava.util.AbstractMap.SimpleEntry

If you look at the documentation of Map.Entry you will find that it is a static interface (an interface which is defined inside the Map interface an can be accessed through Map.Entry) and it has two implementations如果您查看 Map.Entry 的文档,您会发现它是一个静态接口(在 Map 接口内部定义的接口,可以通过 Map.Entry 访问)并且它有两个实现

All Known Implementing Classes:所有已知的实现类:
AbstractMap.SimpleEntry, AbstractMap.SimpleImmutableEntry AbstractMap.SimpleEntry, AbstractMap.SimpleImmutableEntry

The class AbstractMap.SimpleEntry provides 2 constructors: AbstractMap.SimpleEntry类提供了 2 个构造函数:

Constructors and Description构造函数和描述
AbstractMap.SimpleEntry(K key, V value) AbstractMap.SimpleEntry(K 键,V 值)
Creates an entry representing a mapping from the specified key to the创建一个条目,表示从指定键到
specified value.指定值。
AbstractMap.SimpleEntry(Map.Entry<? extends K,? extends V> entry) AbstractMap.SimpleEntry(Map.Entry<? extends K,? extends V> entry)
Creates an entry representing the same mapping as the specified entry.创建一个条目,表示与指定条目相同的映射。

An example use case:一个示例用例:

import java.util.Map;
import java.util.AbstractMap.SimpleEntry;

public class MyClass {
    public static void main(String args[]) {
      Map.Entry e = new SimpleEntry<String, String>("Hello","World");

      System.out.println(e.getKey()+" "+e.getValue());
    }
}

org.apache.commons.lang3.tuple.Pair implements java.util.Map.Entry and can also be used standalone. org.apache.commons.lang3.tuple.Pair实现了java.util.Map.Entry ,也可以独立使用。

Also as others mentioned Guava's com.google.common.collect.Maps.immutableEntry(K, V) does the trick.正如其他人提到的,番石榴的com.google.common.collect.Maps.immutableEntry(K, V)可以解决问题。

I prefer Pair for its fluent Pair.of(L, R) syntax.我更喜欢Pair其流畅的Pair.of(L, R)语法。

I defined a generic Pair class that I use all the time.我定义了一个我一直使用的通用 Pair 类。 It's great.这很棒。 As a bonus, by defining a static factory method (Pair.create) I only have to write the type arguments half as often.作为奖励,通过定义一个静态工厂方法 (Pair.create),我只需编写一半的类型参数。

public class Pair<A, B> {

    private A component1;
    private B component2;

    public Pair() {
            super();
    }

    public Pair(A component1, B component2) {
            this.component1 = component1;
            this.component2 = component2;
    }

    public A fst() {
            return component1;
    }

    public void setComponent1(A component1) {
            this.component1 = component1;
    }

    public B snd() {
            return component2;
    }

    public void setComponent2(B component2) {
            this.component2 = component2;
    }

    @Override
    public String toString() {
            return "<" + component1 + "," + component2 + ">";
    }

    @Override
    public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result
                            + ((component1 == null) ? 0 : component1.hashCode());
            result = prime * result
                            + ((component2 == null) ? 0 : component2.hashCode());
            return result;
    }

    @Override
    public boolean equals(Object obj) {
            if (this == obj)
                    return true;
            if (obj == null)
                    return false;
            if (getClass() != obj.getClass())
                    return false;
            final Pair<?, ?> other = (Pair<?, ?>) obj;
            if (component1 == null) {
                    if (other.component1 != null)
                            return false;
            } else if (!component1.equals(other.component1))
                    return false;
            if (component2 == null) {
                    if (other.component2 != null)
                            return false;
            } else if (!component2.equals(other.component2))
                    return false;
            return true;
    }

    public static <A, B> Pair<A, B> create(A component1, B component2) {
            return new Pair<A, B>(component1, component2);
    }

}

If you are using Clojure, you have another option:如果您使用的是 Clojure,您还有另一种选择:

(defn map-entry
  [k v]
  (clojure.lang.MapEntry/create k v))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM