Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert a key value pair in a Tree map at a particular index

I need to put elements in a Map and I chose the TreeMap implementation, the keys are to be placed in ascending sorted order in the map, but one of the keys which is "unassigned" should always be the first. Is this possible ? My current code only puts the the elements in a sorted order ?

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

}

The current output is

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

I want the output as

{unassigned=?,apple=34, banana=45, carrot=12, domboi=912,zucchini=87}
like image 832
Praneeth Avatar asked May 26 '16 16:05

Praneeth


People also ask

How do I add a key and value in TreeMap?

put() method of TreeMap is used to insert a mapping into a map. This means we can insert a specific key and the value it is mapping to into a particular map. If an existing key is passed then the previous value gets replaced by the new value. If a new pair is passed, then the pair gets inserted as a whole.

Can you index a TreeMap?

We can get a TreeMap key or TreeMap value using an index in Java by using an Array. The process is divided into three steps: Use the entrySet() method of the TreeMap class to get a Set view of all the entries stored in the TreeMap object.

How do I change the value of a TreeMap key?

Ways by which we can replace the value using the given key:Using put() method of TreeMap class. Using replace() method of TreeMap class. Using ComputeIfPresent() method of TreeMap class.


Video Answer


2 Answers

Simply change your Comparator for this:

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

Output:

TreeMap Entries:
{unassigned=?, apple=34, banana=45, carrot=12, domboi=912, zucchini=87}
like image 137
Nicolas Filotto Avatar answered Sep 23 '22 22:09

Nicolas Filotto


Actually, you can inject an element at a certain position. So, for example, the special entry can appear third in the iteration.

Just for fun, I came up with the following abomination. Rather than tinkering with the order, I wrapped a TreeMap together with an extra pseudo-entry. I'm not overly confident about how it will handle entry removal during iteration, but hopefully you get the idea.

I should point out that this map will always have an "unassigned" entry, with a default value of null. If you don't want that, you could use a similar approach, but wait to switch the entries member from a TreeSet to a SillySet when the "unassigned" key is added. Or something like that.

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

}
like image 25
erickson Avatar answered Sep 22 '22 22:09

erickson