如何将特定的 HashMap 条目移动到映射的末尾?

问题描述 投票:0回答:8

如何将特定的

HashMap
条目移动到最后一个位置?

例如,我有

HashMap
这样的值:

HashMap<String,Integer> map = new HashMap<String,Integer>();

// map = {Not-Specified 1, test 2, testtest 3};

“未指定”可以出现在任何位置。它可能出现在地图的最前面或中间。但我想把“未指定”移到最后一个位置。

我该怎么做?

java dictionary hashmap
8个回答
168
投票

用一句话回答你的问题:

默认情况下,地图没有最后一个条目,这不是他们合同的一部分。


还有一个旁注:针对接口而不是实现类进行编码是一种很好的做法(请参阅 Joshua Bloch 的《Effective Java》,第 8 章,第 52 条:通过接口引用对象)。

因此您的声明应为:

Map<String,Integer> map = new HashMap<String,Integer>();

(所有地图共享一个公共合约,因此客户端不需要知道它是什么类型的地图,除非他指定具有扩展合约的子接口)。


可能的解决方案

排序地图:

有一个子接口 SortedMap 使用基于顺序的查找方法扩展了地图接口,并且它还有一个子接口 NavigableMap 进一步扩展了它。该接口的标准实现TreeMap允许您通过自然顺序(如果它们实现了Comparable接口)或通过提供的Comparator对条目进行排序。

您可以通过 lastEntry 方法访问最后一个条目:

NavigableMap<String,Integer> map = new TreeMap<String, Integer>();
// add some entries
Entry<String, Integer> lastEntry = map.lastEntry();

链接地图:

还有LinkedHashMap的特殊情况,它是一种存储键插入顺序的HashMap实现。然而,没有接口来支持此功能,也没有直接的方法来访问最后一个密钥。你只能通过一些技巧来做到这一点,例如在两者之间使用列表:

Map<String,String> map = new LinkedHashMap<String, Integer>();
// add some entries
List<Entry<String,Integer>> entryList =
    new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Entry<String, Integer> lastEntry =
    entryList.get(entryList.size()-1);

正确的解决方案:

由于您无法控制插入顺序,因此您应该使用 NavigableMap 接口,即您将编写一个比较器,将

Not-Specified
条目放在最后。

这是一个例子:

final NavigableMap<String,Integer> map = 
        new TreeMap<String, Integer>(new Comparator<String>() {
    public int compare(final String o1, final String o2) {
        int result;
        if("Not-Specified".equals(o1)) {
            result=1;
        } else if("Not-Specified".equals(o2)) {
            result=-1;
        } else {
            result =o1.compareTo(o2);
        }
        return result;
    }

});
map.put("test", Integer.valueOf(2));
map.put("Not-Specified", Integer.valueOf(1));
map.put("testtest", Integer.valueOf(3));
final Entry<String, Integer> lastEntry = map.lastEntry();
System.out.println("Last key: "+lastEntry.getKey()
         + ", last value: "+lastEntry.getValue());

输出:

最后一个键:未指定,最后一个值:1

使用HashMap的解决方案:

如果您必须依赖 HashMap,仍然有一个解决方案,使用 a) 上述比较器的修改版本,b) 使用 Map 的 entrySet 初始化的 List 和 c) Collections.sort() 帮助器方法:

    final Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("test", Integer.valueOf(2));
    map.put("Not-Specified", Integer.valueOf(1));
    map.put("testtest", Integer.valueOf(3));

    final List<Entry<String, Integer>> entries =
        new ArrayList<Entry<String, Integer>>(map.entrySet());
    Collections.sort(entries, new Comparator<Entry<String, Integer>>(){

        public int compareKeys(final String o1, final String o2){
            int result;
            if("Not-Specified".equals(o1)){
                result = 1;
            } else if("Not-Specified".equals(o2)){
                result = -1;
            } else{
                result = o1.compareTo(o2);
            }
            return result;
        }

        @Override
        public int compare(final Entry<String, Integer> o1,
            final Entry<String, Integer> o2){
            return this.compareKeys(o1.getKey(), o2.getKey());
        }

    });

    final Entry<String, Integer> lastEntry =
        entries.get(entries.size() - 1);
    System.out.println("Last key: " + lastEntry.getKey() + ", last value: "
        + lastEntry.getValue());

}

输出:

最后一个键:未指定,最后一个值:1


19
投票

HashMap 没有 “最后一个位置”,因为它没有排序。

您可以使用其他实现

Map
java.util.SortedMap
,最流行的是
TreeMap


5
投票

A

SortedMap
是逻辑/最佳选择,但是另一种选择是使用
LinkedHashMap
,它维护两种顺序模式,最近添加的放在最后,最近访问的放在最后。有关更多详细信息,请参阅 Javadocs。


2
投票

当使用数字作为键时,我想你也可以尝试这个:

        Map<Long, String> map = new HashMap<>();
        map.put(4L, "The First");
        map.put(6L, "The Second");
        map.put(11L, "The Last");

        long lastKey = 0;
        //you entered Map<Long, String> entry
        for (Map.Entry<Long, String> entry : map.entrySet()) {
            lastKey = entry.getKey();
        }
        System.out.println(lastKey); // 11

1
投票

move 对于 hashmap 来说没有意义,因为它是一个字典,带有用于基于键进行分桶的哈希码,然后是一个通过 equals 解决冲突哈希码的链表。 使用 TreeMap 进行排序映射,然后传入自定义比较器。


0
投票

在这种情况下,最后使用的密钥通常是已知的,因此它可以用于访问最后一个值(与该值一起插入):

class PostIndexData {
    String _office_name;
    Boolean _isGov;
    public PostIndexData(String name, Boolean gov) {
        _office_name = name;
        _isGov = gov;
    }
}
//-----------------------
class KgpData {
    String _postIndex;
    PostIndexData _postIndexData;
    public KgpData(String postIndex, PostIndexData postIndexData) {
        _postIndex = postIndex;
        _postIndexData = postIndexData;;
    }
}

public class Office2ASMPro {
    private HashMap<String,PostIndexData> _postIndexMap = new HashMap<>();
    private HashMap<String,KgpData> _kgpMap = new HashMap<>();
...
private void addOffice(String kgp, String postIndex, String officeName, Boolean gov) {
            if (_postIndexMap.get(postIndex) == null) {
                _postIndexMap.put(postIndex, new PostIndexData(officeName, gov));
            }
            _kgpMap.put( kgp, new KgpData(postIndex, _postIndexMap.get(postIndex)) );
        }

0
投票

HashMap
明确没有定义按键顺序。根据类 Javadocs

此类不保证地图的顺序;特别是,它不能保证顺序随着时间的推移保持不变。

许多其他地图类型确实定义了按键顺序,包括

LinkedHashMap
和实现
SortedMap
接口的地图。 Java 21 为此类地图引入了
SequencedMap
接口,这些地图具有明确定义的遭遇顺序。

根据 其 Javadocs

SequencedMap
是:

A

Map
,具有明确定义的遭遇顺序,支持两端操作,并且是可逆的。

SequencedMap
的操作之一是
putLast
。对于支持它的
SequencedMap
类型,此可选操作会在映射的末尾插入一个条目,或者如果键已存在,则将其移动到末尾。
LinkedHashMap
支持此方法,但
SortedMap
不支持。根据 Javadocs 方法

如果给定映射尚不存在,则将其插入到映射中;如果映射已经存在,则替换映射的值(可选操作)。此操作正常完成后,给定的映射将出现在该地图中,并且它将是该地图的遭遇顺序中的最后一个映射。

相关场景

将上述内容应用到您所讨论的场景中,我们得到:

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

populateMap(map); // Populate the map as: {Not-Specified 1, test 2, testtest 3};

map.putLast("Not-Specified", map.get("Not-Specified"));

-2
投票
Find missing all elements from array
        int[] array = {3,5,7,8,2,1,32,5,7,9,30,5};
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for(int i=0;i<array.length;i++) {
            map.put(array[i], 1);
        }
        int maxSize = map.lastKey();
        for(int j=0;j<maxSize;j++) {
            if(null == map.get(j))
                System.out.println("Missing `enter code here`No:"+j);
        }
© www.soinside.com 2019 - 2024. All rights reserved.