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

发布于 2024-09-15 08:52:08 字数 359 浏览 6 评论 0 原文

如何将特定的HashMap条目移动到最后一个位置?

例如,我有像这样的 HashMap 值:

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

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

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

我怎样才能做到这一点?

How to move a particular HashMap entry to the last position?

For example, I have HashMap values like this:

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

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

"Not-Specified" may come in any position. it may come first or in the middle of the map. But I want to move the "Not-Specified" to the last position.

How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

哭泣的笑容 2024-09-22 08:52:08

用一句话回答您的问题:

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


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

所以你的声明应该这样写:(

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

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


可能的解决方案

Sorted Maps:

有一个子接口 SortedMap< /a> 使用基于顺序的查找方法扩展了地图接口,它有一个子接口 NavigableMap 进一步扩展了它。该接口的标准实现,TreeMap ,允许您按自然顺序对条目进行排序(如果它们实现 可比较接口)或通过提供的 比较器

您可以通过 访问最后一个条目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);

Java 21 中的 SequencedMap 接口为 LinkedHashMap 提供了 lastEntry 方法获取最后一个条目:

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

正确的解决方案:

因为您不这样做如果不控制插入顺序,您应该使用 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) a List 使用地图的 entrySet 和 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

To answer your question in one sentence:

Per default, Maps don't have a last entry, it's not part of their contract.


And a side note: it's good practice to code against interfaces, not the implementation classes (see Effective Java by Joshua Bloch, Chapter 8, Item 52: Refer to objects by their interfaces).

So your declaration should read:

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

(All maps share a common contract, so the client need not know what kind of map it is, unless he specifies a sub interface with an extended contract).


Possible Solutions

Sorted Maps:

There is a sub interface SortedMap that extends the map interface with order-based lookup methods and it has a sub interface NavigableMap that extends it even further. The standard implementation of this interface, TreeMap, allows you to sort entries either by natural ordering (if they implement the Comparable interface) or by a supplied Comparator.

You can access the last entry through the lastEntry method:

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

Linked maps:

There is also the special case of LinkedHashMap, a HashMap implementation that stores the order in which keys are inserted. Prior to the introduction of SequencedMap in Java 21, there was however no interface to back up this functionality, nor was there a direct way to access the last key. You could only do it through tricks such as using a List in between:

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

The SequencedMap interface in Java 21 provides LinkedHashMap with the lastEntry method to get the last entry:

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

Proper Solution:

Since you don't control the insertion order, you should go with the NavigableMap interface, i.e. you would write a comparator that positions the Not-Specified entry last.

Here is an example:

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

Output:

Last key: Not-Specified, last value: 1

Solution using HashMap:

If you must rely on HashMaps, there is still a solution, using a) a modified version of the above comparator, b) a List initialized with the Map's entrySet and c) the Collections.sort() helper method:

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

}

Output:

Last key: Not-Specified, last value: 1

星星的轨迹 2024-09-22 08:52:08

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

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

HashMap doesn't have "the last position", as it is not sorted.

You may use other Map which implements java.util.SortedMap, most popular one is TreeMap.

独享拥抱 2024-09-22 08:52:08

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

A SortedMap is the logical/best choice, however another option is to use a LinkedHashMap which maintains two order modes, most-recently-added goes last, and most-recently-accessed goes last. See the Javadocs for more details.

暗藏城府 2024-09-22 08:52:08

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

        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

When using numbers as the key, I suppose you could also try this:

        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
你是年少的欢喜 2024-09-22 08:52:08

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

move does not make sense for a hashmap since its a dictionary with a hashcode for bucketing based on key and then a linked list for colliding hashcodes resolved via equals.
Use a TreeMap for sorted maps and then pass in a custom comparator.

桜花祭 2024-09-22 08:52:08

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

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

In such scenario last used key is usually known so it can be used for accessing last value (inserted with the one):

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)) );
        }
丑疤怪 2024-09-22 08:52:08

HashMap 明确未定义键顺序。根据类 Javadocs

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

许多其他映射类型确实定义了键顺序,包括 LinkedHashMap 和实现 SortedMap 接口。 Java 21 引入了 SequencedMap 地图接口,例如具有明确定义的遭遇顺序的地图。

根据 其 Javadocs< /a>,SequencedMap 是:

一个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"));

HashMap explicitly does not define a key order. Per the class Javadocs:

This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

A number other map types do define a key order, including LinkedHashMap and maps which implement the SortedMap interface. Java 21 introduced the SequencedMap interface for maps such as these which have a a well-defined encounter order.

Per its Javadocs, a SequencedMap is:

A Map that has a well-defined encounter order, that supports operations at both ends, and that is reversible.

One of the operations on SequencedMap is putLast. This optional operation, for SequencedMap types that support it, inserts an entry at the end of the map, or moves it to the end if the key is already present. LinkedHashMap supports this method, but SortedMap does not. Per the method Javadocs:

Inserts the given mapping into the map if it is not already present, or replaces the value of a mapping if it is already present (optional operation). After this operation completes normally, the given mapping will be present in this map, and it will be the last mapping in this map's encounter order.

Scenario in question

Applying the above to your scenario in question, we get:

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"));
不知在何时 2024-09-22 08:52:08
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);
        }
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);
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文