在Tree map中的特定索引处插入一个键值对。

5

我需要将元素放入一个Map中,我选择了TreeMap实现方式,在map中,键应该按升序排序,但是其中一个键“unassigned”应该始终排在第一位。这个是否可能?我的当前代码只能按照排序顺序放置元素。

public class TreeMapTest {

    public static void main(String args[]){
        //the treemap sorts by key
        Map<String, String> hm = new TreeMap<String, String>(new StringComparator());
        //add key-value pair to TreeMap
        hm.put("carrot","12");
        hm.put("apple", "34");
        hm.put("domboi","912");
        hm.put("unassigned","?");
        hm.put("banana", "45");  
        hm.put("zucchini","87");
        System.out.println("TreeMap Entries:");
        System.out.println(hm);

    }
}

class StringComparator implements Comparator<String>{

    @Override
    public int compare(String str1, String str2) {
        return str1.compareTo(str2);
    }

}

当前输出为:
{apple=34, banana=45, carrot=12, domboi=912, unassigned=?, zucchini=87} 

我希望得到的输出是:
{unassigned=?,apple=34, banana=45, carrot=12, domboi=912,zucchini=87}
2个回答

6
只需更改您的 Comparator 为以下内容:
class StringComparator implements Comparator<String> {

    @Override
    public int compare(String str1, String str2) {
        if (str1.equals(str2)) {
            return 0;
        } else if ("unassigned".equals(str1)) {
            return -1;
        } else if ("unassigned".equals(str2)) {
            return 1;
        }
        return str1.compareTo(str2);
    }
}

输出:

TreeMap Entries:
{unassigned=?, apple=34, banana=45, carrot=12, domboi=912, zucchini=87}

它有效了,如此简单的解决方案,目前解决了问题,谢谢!但是如果我想将我的键放在地图中的第三个位置呢? - Praneeth
@Praneeth,那你就没什么办法了。实际上没有办法做到那样的事情。 - Louis Wasserman
1
实际上,@NicolasFilotto,你的“Comparator”实现将会出现严重问题。map.get("unassigned")将始终返回null。如果参数相等,你必须返回0 - Louis Wasserman
@LouisWasserman 请查看我的神奇SillyMap,它允许在指定位置放置一个映射条目! - erickson
@LouisWasserman,是的,你说得对,Nicolas编写的原始代码中存在一个错误,就像你所说的get("unassigned")没有正常工作,这导致它插入了多个具有相同名称“unassigned”的键,我很惊讶这是怎么发生的,现在已经修复了。谢谢大家。顺便说一句,str1.compareTo(str2)无论如何都会检查相等的情况并返回0,对吗?为什么要添加另一个if条件来返回0(我知道这解决了问题)? - Praneeth

1

实际上,您可以在特定位置注入一个元素。因此,例如,特殊条目可以出现在迭代的第三个位置。

只是为了好玩,我想出了以下可怕的方法。而不是调整顺序,我将TreeMap与额外的伪条目一起包装。我对它在迭代期间如何处理条目删除并不十分自信,但希望您能理解这个想法。

我应该指出,此映射将始终具有“未分配”条目,默认值为null。如果您不想要它,可以使用类似的方法,但在添加“未分配”键时等待将entries成员从TreeSet切换到SillySet。或者类似的东西。

import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;

final class SillyMap<K, V>
  extends AbstractMap<K, V>
{

  private final SillySet entries;

  SillyMap(K key, int unassigned)
  {
    entries = new SillySet(key, unassigned);
  }

  @Override
  public Set<Map.Entry<K, V>> entrySet()
  {
    return entries;
  }

  @Override
  public V put(K key, V value)
  {
    if (entries.extra.getKey().equals(key))
      return entries.extra.setValue(value);
    else
      return entries.map.put(key, value);
  }

  private final class SillySet
    extends AbstractSet<Map.Entry<K, V>>
  {

    final Map<K, V> map = new TreeMap<>();

    final Map.Entry<K, V> extra;

    private final int unassigned;

    SillySet(K key, int unassigned)
    {
      extra = new SimpleEntry<>(Objects.requireNonNull(key), null);
      if (unassigned < 0)
        throw new IllegalArgumentException();
      this.unassigned = unassigned;
    }

    @Override
    public Iterator<Map.Entry<K, V>> iterator()
    {
      return new Iterator<Map.Entry<K, V>>()
      {

        private final Iterator<Map.Entry<K, V>> i = map.entrySet().iterator();

        private int index = 0;

        @Override
        public boolean hasNext()
        {
          return index < size();
        }

        @Override
        public Map.Entry<K, V> next()
        {
          Map.Entry<K, V> e;
          if (index == Math.min(unassigned, map.size()))
            e = extra;
          else
            e = i.next();
          ++index;
          return e;
        }

        @Override
        public void remove()
        {
          if (index - 1 == unassigned)
            throw new UnsupportedOperationException();
          i.remove();
          --index;
        }

      };
    }

    @Override
    public int size()
    {
      return map.size() + 1;
    }

  };

  public static void main(String... argv)
  {
    final String KEY = "unassigned";
    Map<String, String> hm = new SillyMap<>(KEY, 3);
    hm.put("carrot", "12");
    hm.put("apple", "34");
    hm.put("domboi", "912");
    hm.put(KEY, "?");
    hm.put("banana", "45");
    hm.put("zucchini", "87");
    System.out.println(hm);
  }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接