Java - Cách tạo Entry mới (khóa, giá trị)


291

Tôi muốn tạo một mục mới tương tự như vậy Util.Map.Entrysẽ chứa cấu trúc key, value.

Vấn đề là tôi không thể khởi tạo một Map.Entryvì nó là một giao diện.

Có ai biết cách tạo một đối tượng khóa / giá trị chung mới cho Map.Entry không?

Câu trả lời:


79

Bạn chỉ có thể tự thực hiện Map.Entry<K, V>giao diện:

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

Và sau đó sử dụng nó:

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

117
tất nhiên - tôi chỉ tự hỏi liệu không có giải pháp vượt trội nào cho nó. Tôi đang cố gắng làm cho mã của mình chuẩn nhất có thể ...
Người nhện

1
Bạn có thể giải thích lý do tại sao một số triển khai của Map có khóa là cuối cùng (như trong HashMap, ConcảnHashMap), nhưng không phải trong một số triển khai khác như TreeMap, WeakHashMap không?
AKS

7
Mã đã cho không hoàn toàn chính xác vì nó không ghi đè bằng và mã băm cũng được yêu cầu bởi giao diện Map.Entry
John Tang Boyland

Kể từ Java 7 Update 80, tôi đã triển khai ở trên và nó đã hoạt động ( pastebin ). Không có phương pháp nào khác được ghi đè.
bạc

807

public static class AbstractMap.SimpleEntry<K,V>. Đừng để Abstractphần tên đánh lừa bạn: thực tế nó KHÔNG phải là một abstractlớp (nhưng cấp cao nhất của nó AbstractMaplà).

Thực tế rằng đó là một staticlớp lồng nhau có nghĩa là bạn KHÔNG cần một AbstractMapcá thể kèm theo để khởi tạo nó, vì vậy một cái gì đó như thế này sẽ biên dịch tốt:

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

Như đã lưu ý trong một câu trả lời khác, Guava cũng có một staticphương pháp nhà máy thuận tiện Maps.immutableEntrymà bạn có thể sử dụng.


Bạn đã nói:

Tôi không thể sử dụng Map.Entrychính nó vì rõ ràng đó là một đối tượng chỉ đọc mà tôi không thể khởi tạo mớiinstanceof

Điều đó không hoàn toàn chính xác. Lý do tại sao bạn không thể khởi tạo nó trực tiếp (tức là với new) là vì đó là một interface Map.Entry.


Hãy cẩn thận và tiền boa

Như đã lưu ý trong tài liệu AbstractMap.SimpleEntrynày @since 1.6, vì vậy, nếu bạn bị kẹt ở 5.0, thì nó không có sẵn cho bạn.

Để tìm một lớp đã biết khác implements Map.Entry, trên thực tế bạn có thể truy cập trực tiếp vào javadoc. Từ phiên bản Java 6

Giao diện bản đồ.Entry

Tất cả các lớp triển khai đã biết :

Thật không may, phiên bản 1.5 không liệt kê bất kỳ lớp triển khai đã biết nào mà bạn có thể sử dụng, do đó bạn có thể bị mắc kẹt với việc triển khai của riêng bạn.


Dòng trên trả về lỗi biên dịch cho tôi (Tôi đang sử dụng java 5, BTW) - thông báo lỗi là: 'Loại AbstractMap.SimpleEntry không hiển thị'
Người nhện

6
Đó là vì AbstractMap.SimpleEntrykhông công khai cho đến Java 6, như bạn có thể thấy trong tài liệu.
Jesper

OK, vì vậy để tóm tắt cuộc thảo luận ngắn - không có giải pháp vượt trội nào cho nó trong Java 5 - Tôi nên sử dụng triển khai của riêng mình cho nó.
Người nhện

4
+1 để chỉ ra AbstractMap.SimpleEntry. Tôi đoán bạn học được một vài thứ mới mỗi ngày!
Priidu Neemre

ý bạn là gì khi kèm theo "một ví dụ Tóm tắt Bản đồ kèm theo". Là bao gồm suy luận một thuật ngữ kỹ thuật hoặc một cái gì đó trong java? xin vui lòng hướng dẫn cho tôi.
Đồ họa C

70

Bắt đầu từ Java 9, có một phương thức tiện ích mới cho phép tạo ra một mục bất biến Map#entry(Object, Object).

Đây là một ví dụ đơn giản:

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

Như nó là bất biến, gọi setValuesẽ ném một UnsupportedOperationException. Những hạn chế khác là thực tế là nó không được tuần tự hóa và nullvì khóa hoặc giá trị bị cấm, nếu nó không được chấp nhận cho bạn, bạn sẽ cần phải sử dụng AbstractMap.SimpleImmutableEntryhoặc AbstractMap.SimpleEntrythay vào đó.

Lưu ý: Nếu nhu cầu của bạn là tạo trực tiếp a Mapvới các cặp từ 0 đến tối đa 10 (khóa, giá trị), thay vào đó bạn có thể sử dụng các phương thức loại Map.of(K key1, V value1, ...).


53

Hãy dùng thử Maps.immutableEntry từ ổi

Điều này có lợi thế là tương thích với Java 5 (không giống như AbstractMap.SimpleEntryyêu cầu Java 6.)


34

Ví dụ về AbstractMap.SimpleEntry:

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

Khởi tạo:

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

Thêm hàng:

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

Lấy các hàng:

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());

Nên in:

2
3
20
30
2
4

Nó tốt cho việc xác định các cạnh của cấu trúc đồ thị. Giống như những người giữa các tế bào thần kinh trong đầu của bạn.


18

Bạn thực sự có thể đi với: Map.Entry<String, String> en= Maps.immutableEntry(key, value);


Nó rất hữu ích. github.com/google/guava Guava là một bộ thư viện Java cốt lõi của Google bao gồm các loại bộ sưu tập mới (như multimap và multiset), các bộ sưu tập bất biến, thư viện đồ thị và các tiện ích để tương tranh, I / O, băm, lưu trữ, nguyên thủy, chuỗi, và nhiều hơn nữa! Nó được sử dụng rộng rãi trên hầu hết các dự án Java trong Google và cũng được sử dụng rộng rãi bởi nhiều công ty khác.
Languoguang

13

Tại sao Map.Entry? Tôi đoán một cái gì đó giống như một cặp khóa-giá trị là phù hợp cho trường hợp.

Sử dụng java.util.AbstractMap.SimpleImmutableEntryhoặcjava.util.AbstractMap.SimpleEntry


6

org.apache.commons.lang3.tuple.Pairthực hiện java.util.Map.Entryvà cũng có thể được sử dụng độc lập.

Cũng như những người khác đã đề cập đến Guava com.google.common.collect.Maps.immutableEntry(K, V).

Tôi thích cú pháp Pairtrôi chảy của nó Pair.of(L, R).


2
Tôi có thể đề nghị ImmutablePairthay thế?
beluchin

Tôi thực sự thích lớp org.apache.commons.lang3.tuple.Pair, thật tuyệt vời!
Laurens Op 't Zandt

Điều duy nhất tôi không thích về nó là nó được tuần tự hóa sang trái, phải, khóa, giá trị trong đó left = key và right = value. Chỉ cần thêm 2 giá trị vô dụng (có thể) trong chuỗi nối tiếp.
Vikrant Goel

4

Tôi đã định nghĩa một lớp Pair chung mà tôi sử dụng mọi lúc. Thật tuyệt vời. Như một phần thưởng, bằng cách xác định một phương thức nhà máy tĩnh (Pair.create), tôi chỉ phải viết các đối số kiểu một nửa thường xuyên.

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

}

1
Xin lỗi, tôi đã đăng bài này trước khi đọc tất cả các bình luận khác. Có vẻ như bạn muốn một cái gì đó được bao gồm trong lib tiêu chuẩn ...
Nels Beckman

2
Google Guava đưa ra quan điểm tốt về lý do tại sao Pairviệc triển khai là một điều xấu. Nguồn
Ingo Bürk

3

Nếu bạn đang sử dụng Clojure, bạn có một tùy chọn khác:

(defn map-entry
  [k v]
  (clojure.lang.MapEntry/create k v))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.