访问 Map 中的最后一个条目

Posted

技术标签:

【中文标题】访问 Map 中的最后一个条目【英文标题】:Accessing the last entry in a Map 【发布时间】:2011-04-01 10:20:09 【问题描述】:

如何将特定的 HashMap 条目移动到 Last 位置?

例如,我有这样的 HashMap 值:

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

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

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

我该怎么做?提前致谢。

【问题讨论】:

你能解释一下,你为什么要这样做?也许使用 HashMap 不是解决问题的最佳方法。 另见***.com/questions/1936462/… 【参考方案1】:

一句话回答你的问题:

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


附带说明:最好针对接口而不是实现类进行编码(参见Effective Java by Joshua Bloch,第 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 实现。然而,没有接口来备份这个功能,也没有直接的方法来访问最后一个键。您只能通过诸如在两者之间使用 List 之类的技巧来做到这一点:

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的解决方案:

如果您必须依赖 HashMaps,仍然有一个解决方案,使用 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

【讨论】:

为什么实现类似的接口然后使用 TreeMap 不是您的首选?你似乎比我更了解地图,所以只是想知道 @nixxbb 它我的第一选择,这就是为什么它直接出现在字面答案之后 哦,我明白了,您在谈论 Comparable vs Comparator。在 OP 的情况下,键是字符串,但他需要自定义顺序。这就是为什么。否则我会同意你的意见 哦,我明白了。做得很好。谢谢你的回复,我从你的回答中学到了很多...【参考方案2】:

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

你可以使用其他实现java.util.SortedMapMap,最流行的是TreeMap

【讨论】:

另见***.com/questions/1936462/…【参考方案3】:

SortedMap 是合乎逻辑的/最佳选择,但另一种选择是使用LinkedHashMap,它保持两种排序模式,最近添加的排在最后,最近访问的排在最后。有关详细信息,请参阅 Javadocs。

【讨论】:

【参考方案4】:

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

        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

【讨论】:

【参考方案5】:

move 对 hashmap 没有意义,因为它是一个字典,其中包含一个 hashcode,用于基于 key 进行分桶,然后是一个链表,用于通过 equals 解决冲突的 hashcode。 将 TreeMap 用于排序的地图,然后传入自定义比较器。

【讨论】:

创建后不能使用 TreeMap “传入自定义比较器”。您只能将其用作构造函数参数。【参考方案6】:

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

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

【讨论】:

您好,Mad Calm,请记住尽量使您的示例简洁明了,以便阅读问题/答案的任何人都能轻松理解。在没有太多解释的情况下粘贴代码通常不是一个好主意 :-) 感谢您的贡献。【参考方案7】:
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);
        

【讨论】:

从数组中查找缺失的所有元素 这看起来与提出的问题没有太大关系。

以上是关于访问 Map 中的最后一个条目的主要内容,如果未能解决你的问题,请参考以下文章

Flutter/Dart:如何访问地图/对象中的单个条目

访问 Core Data 中的特定条目

删除 Eclipse Juno 中的“快速访问”条目

Symfony 表单 - 在 CollectionType 中的子条目类型中访问实体

模板中的多对多通过模型中的 Django 访问条目

从列表条目访问 SQL 数据