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?
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?
Câu trả lời:
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.
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);
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 LinkedHashMap
trá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 ] );
}
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]);
String myKey = keys[i].toString();
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ó.
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.
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;
}
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.
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
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.
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);
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 đồ.
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.