Có thể lấy phần tử từ HashMap theo vị trí của nó không?


99

Làm thế nào để truy xuất một phần tử từ HashMap theo vị trí của nó, có khả thi không?


11
Bạn hiểu "vị trí" là gì? HashMaps không được sắp xếp theo thứ tự, vì vậy chúng không có khái niệm thông thường về "vị trí" mà bạn sẽ nhận được với một cái gì đó như Vector.
Mat

1
Ý bạn là do thứ tự chèn của nó hay một số thứ tự khác?
Mark Elliot

Câu trả lời:


94

HashMaps không bảo toàn thứ tự:

Lớp này không đảm bảo về thứ tự của bản đồ; đặc biệt, nó không đảm bảo rằng đơn hàng sẽ không đổi theo thời gian.

Hãy xem LinkedHashMap , đảm bảo thứ tự lặp lại có thể dự đoán được.


16
Điều này không thực sự trả lời câu hỏi. Các câu trả lời khác bên dưới hữu ích hơn.
forresthopkinsa

6
Về sự tôn trọng, điều này trích dẫn tài liệu trực tiếp trả lời câu hỏi
Wayne

1
Ngay cả khi thứ tự không thay đổi theo thời gian, vẫn có thể lấy một trong các thành viên theo một vị trí nhất định.
Người mới bắt đầu

Tôi không làm theo. Giải thích?
Wayne

Liên kết HashMap bị hỏng / 404.
Raf

109

Sử dụng LinkedHashMap và khi bạn cần truy xuất theo vị trí, hãy chuyển đổi các giá trị thành ArrayList.

LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<String,String>();
/* Populate */
linkedHashMap.put("key0","value0");
linkedHashMap.put("key1","value1");
linkedHashMap.put("key2","value2");
/* Get by position */
int pos = 1;
String value = (new ArrayList<String>(linkedHashMap.values())).get(pos);

2
Luôn luôn cần thiết để khởi tạo một bản sao của các khóa từ HashMap ??
Richard

điều này sẽ tạo một đối tượng ArrayList mới mỗi khi chúng tôi truy xuất giá trị, dẫn đến rò rỉ bộ nhớ
NullByte08

48

Nếu bạn muốn duy trì thứ tự mà bạn đã thêm các phần tử vào bản đồ, hãy sử dụng LinkedHashMaptrái ngược với chỉ HashMap.

Đây là một cách tiếp cận sẽ cho phép bạn nhận một giá trị theo chỉ mục của nó trong bản đồ:

public Object getElementByIndex(LinkedHashMap map,int index){
    return map.get( (map.keySet().toArray())[ index ] );
}

1
Tôi phải nói đơn giản nhất ... Thay vì chuyển đổi mọi thứ, bạn đang chỉ sử dụng bộ bàn phím. Tuyệt vời
kirtan403

19

Nếu vì lý do nào đó, bạn phải gắn bó với Bản đồ băm, bạn có thể chuyển đổi keySet thành một mảng và lập chỉ mục các khóa trong mảng để nhận các giá trị trong bản đồ như sau:

Object[] keys = map.keySet().toArray();

Sau đó, bạn có thể truy cập bản đồ như:

map.get(keys[i]);

Lưu ý rằng arr [i] nên đổi thành: Phím [i]
Mohsen Abasi

Ok, tôi có Strings như phím bản đồ, để có được một trong những họ, phần thứ hai sẽ là:String myKey = keys[i].toString();
Orici

12

Sử dụng LinkedHashMap:

Bảng băm và triển khai danh sách liên kết của giao diện Bản đồ, với thứ tự lặp lại có thể dự đoán được. Việc triển khai này khác với HashMap ở chỗ nó duy trì một danh sách được liên kết kép chạy qua tất cả các mục của nó.


27
điều đó sẽ bảo toàn đơn đặt hàng, nhưng bạn vẫn không thể truy cập các mục theo chỉ mục của chúng. Bạn sẽ phải lặp lại
Bozho

liên kết này là một phiên bản cũ của API. Tôi khuyên bạn nên liên kết với một API Java 6 hoặc 7.
jzd

6

Sử dụng LinkedHashMap và sử dụng chức năng này.

private LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>();

Xác định như thế này và.

private Entry getEntry(int id){
        Iterator iterator = map.entrySet().iterator();
        int n = 0;
        while(iterator.hasNext()){
            Entry entry = (Entry) iterator.next();
            if(n == id){
                return entry;
            }
            n ++;
        }
        return null;
    }

Hàm có thể trả về mục đã chọn.


3

Tôi giả định theo 'vị trí' bạn đang đề cập đến thứ tự mà bạn đã chèn các phần tử vào HashMap. Trong trường hợp đó, bạn muốn sử dụng Bản đồ liên kết. Tuy nhiên, LinkedHashMap không cung cấp phương thức truy cập; bạn sẽ cần viết một cái như thế

public Object getElementAt(LinkedHashMap map, int index) {
    for (Map.Entry entry : map.entrySet()) {
        if (index-- == 0) {
            return entry.value();
        }
    }
    return null;
}

3

Một cách tiếp cận làm việc khác là chuyển đổi các giá trị bản đồ thành một mảng và sau đó truy xuất phần tử tại chỉ mục. Chạy thử nghiệm 100 000 phần tử bằng cách tìm kiếm theo chỉ mục trong LinkedHashMap của 100 000 đối tượng bằng cách sử dụng các cách tiếp cận sau đây đã dẫn đến các kết quả sau:

//My answer:
public Particle getElementByIndex(LinkedHashMap<Point, Particle> map,int index){
    return map.values().toArray(new Particle[map.values().size()])[index];
} //68 965 ms

//Syd Lambert's answer:
public Particle getElementByIndex(LinkedHashMap<Point, Particle> map,int index){
    return map.get( (map.keySet().toArray())[ index ] );
} //80 700 ms

Tất cả trong tất cả các phần tử truy xuất theo chỉ mục từ LinkedHashMap dường như là hoạt động khá nặng.


2

HashMap - và cấu trúc dữ liệu cơ bản - bảng băm, không có khái niệm về vị trí. Không giống như LinkedList hoặc Vector, khóa đầu vào được chuyển đổi thành 'thùng' nơi lưu trữ giá trị. Các nhóm này không được sắp xếp theo cách có ý nghĩa bên ngoài giao diện HashMap và như vậy, các mục bạn đưa vào HashMap không theo thứ tự mà bạn mong đợi với các cấu trúc dữ liệu khác


2

HashMap không có khái niệm về vị trí nên không có cách nào để lấy một đối tượng theo vị trí. Các đối tượng trong Maps được thiết lập và lấy bằng các phím.


2

bạn có thể sử dụng mã dưới đây để nhận khóa: String [] keys = (String[]) item.keySet().toArray(new String[0]);

và lấy đối tượng hoặc danh sách chèn vào HashMap với khóa của mục này như sau: item.get(keys[position]);


2

Theo mặc định, java LinkedHasMap không hỗ trợ lấy giá trị theo vị trí. Vì vậy, tôi khuyên bạn nên đi với tùy chỉnhIndexedLinkedHashMap

public class IndexedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {

    private ArrayList<K> keysList = new ArrayList<>();

    public void add(K key, V val) {
        super.put(key, val);
        keysList.add(key);
    }

    public void update(K key, V val) {
        super.put(key, val);
    }

    public void removeItemByKey(K key) {
        super.remove(key);
        keysList.remove(key);
    }

    public void removeItemByIndex(int index) {
        super.remove(keysList.get(index));
        keysList.remove(index);
    }

    public V getItemByIndex(int i) {
        return (V) super.get(keysList.get(i));
    }

    public int getIndexByKey(K key) {
        return keysList.indexOf(key);
    }
}

Sau đó, bạn có thể sử dụng LinkedHasMap tùy chỉnh này như

IndexedLinkedHashMap<String,UserModel> indexedLinkedHashMap=new IndexedLinkedHashMap<>();

ĐỂ thêm giá trị

indexedLinkedHashMap.add("key1",UserModel);

Để getValue theo chỉ mục

indexedLinkedHashMap.getItemByIndex(position);

1

HashMaps không cho phép truy cập theo vị trí, nó chỉ biết về mã băm và nó có thể truy xuất giá trị nếu nó có thể tính toán mã băm của khóa. TreeMaps có một khái niệm về thứ tự. Bản đồ Linkedhas bảo toàn thứ tự mà chúng đã nhập vào bản đồ.


0

Bạn có thể thử triển khai một cái gì đó như vậy, hãy xem:

Map<String, Integer> map = new LinkedHashMap<String, Integer>();
map.put("juan", 2);
map.put("pedro", 3);
map.put("pablo", 5);
map.put("iphoncio",9)

List<String> indexes = new ArrayList<String>(map.keySet()); // <== Parse

System.out.println(indexes.indexOf("juan"));     // ==> 0
System.out.println(indexes.indexOf("iphoncio"));      // ==> 3

Tôi mong công việc này phù hợp với bạn.

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.