Question

The use of null values in a map is problematic, as there is then no way to differentiate whether ...

The use of null values in a map is problematic, as there is then no way to differentiate whether a null value returned by the call get(k) represents the legitimate value of an entry (k, null), or designates that key k was not found. The java.util.Map interface includes a boolean method, containsKey(k), that resolves any such ambiguity.

Implement the containKey(k) method for the SortedTableMap class. Hint: Use the existing findIndex(k) method.

Write a Java application to test your solution.

L i n k to the project (remove spaces): http :// homepage. cs. uiowa. edu/ ~bmccune / 021/ files / maps /

0 0
Add a comment Improve this question Transcribed image text
Answer #1

Hello, I have answered this question before. Also included a Test class which just simply demonstrates the working of new method. Here is the completed code for this problem. Comments are included, go through it, learn how things work and let me know if you have any doubts or if you need anything to change. If you are satisfied with the solution, please rate the answer. Thanks

// SortedTableMap.java (modified)

import java.util.ArrayList;

import java.util.Comparator;

/**

* An implementation of a map using a sorted table. All accessors run in O(log

* n) worst-case time, other than subMap, which runs in O(s + log n) where s is

* the size of the resulting submap, and the complete iterations that run in

* O(n) time.

*

* @author Michael T. Goodrich

* @author Roberto Tamassia

* @author Michael H. Goldwasser

*/

public class SortedTableMap<K, V> extends AbstractSortedMap<K, V> {

      private ArrayList<MapEntry<K, V>> table = new ArrayList<MapEntry<K, V>>();

      /** Constructs an empty map using the natural ordering of keys. */

      public SortedTableMap() {

            super();

      }

      /**

      * Constructs an empty map using the given comparator to order keys.

      *

      * @param comp

      *            comparator defining the order of keys in the map

      */

      public SortedTableMap(Comparator<K> comp) {

            super(comp);

      }

      // variant of binary search that returns relevant index

      /**

      * Returns the smallest index for range table[low..high] inclusive storing

      * an entry with a key greater than or equal to the given k. If no such

      * element exists, returns index high+1 by convention.

      *

      * @param key

      *            the query key

      * @param low

      *            the lowest index of the relevant table range

      * @param high

      *            the highest index of the relevant table range

      * @return lowest j such that table[j] has key greater than or equal to

      *         given key (or index high+1 if no such entry exists)

      */

      private int findIndex(K key, int low, int high) {

            if (high < low)

                  return high + 1; // no entry qualifies

            int mid = (low + high) / 2;

            int comp = compare(key, table.get(mid));

            if (comp == 0)

                  return mid; // found exact match

            else if (comp < 0)

                  return findIndex(key, low, mid - 1); // answer is left of mid (or

                                                                               // possibly mid)

            else

                  return findIndex(key, mid + 1, high); // answer is right of mid

      }

      /** Version of findIndex that searches the entire table */

      private int findIndex(K key) {

            return findIndex(key, 0, table.size() - 1);

      }

      /**

      * Returns the number of entries in the map.

      *

      * @return number of entries in the map

      */

      @Override

      public int size() {

            return table.size();

      }

      /**

      * Returns the value associated with the specified key, or null if no such

      * entry exists.

      *

      * @param key

      *            the key whose associated value is to be returned

      * @return the associated value, or null if no such entry exists

      */

      @Override

      public V get(K key) throws IllegalArgumentException {

            checkKey(key);

            int j = findIndex(key);

            if (j == size() || compare(key, table.get(j)) != 0)

                  return null; // no match

            return table.get(j).getValue();

      }

      /**

      * Associates the given value with the given key. If an entry with the key

      * was already in the map, this replaced the previous value with the new one

      * and returns the old value. Otherwise, a new entry is added and null is

      * returned.

      *

      * @param key

      *            key with which the specified value is to be associated

      * @param value

      *            value to be associated with the specified key

      * @return the previous value associated with the key (or null, if no such

      *         entry)

      */

      @Override

      public V put(K key, V value) throws IllegalArgumentException {

            checkKey(key);

            int j = findIndex(key);

            if (j < size() && compare(key, table.get(j)) == 0) // match exists

                  return table.get(j).setValue(value);

            table.add(j, new MapEntry<K, V>(key, value)); // otherwise new

            return null;

      }

      /**

      * Removes the entry with the specified key, if present, and returns its

      * associated value. Otherwise does nothing and returns null.

      *

      * @param key

      *            the key whose entry is to be removed from the map

      * @return the previous value associated with the removed key, or null if no

      *         such entry exists

      */

      @Override

      public V remove(K key) throws IllegalArgumentException {

            checkKey(key);

            int j = findIndex(key);

            if (j == size() || compare(key, table.get(j)) != 0)

                  return null; // no match

            return table.remove(j).getValue();

      }

      /**

      * Utility returns the entry at index j, or else null if j is out of bounds.

      */

      private Entry<K, V> safeEntry(int j) {

            if (j < 0 || j >= table.size())

                  return null;

            return table.get(j);

      }

      /**

      * Returns the entry having the least key (or null if map is empty).

      *

      * @return entry with least key (or null if map is empty)

      */

      @Override

      public Entry<K, V> firstEntry() {

            return safeEntry(0);

      }

      /**

      * Returns the entry having the greatest key (or null if map is empty).

      *

      * @return entry with greatest key (or null if map is empty)

      */

      @Override

      public Entry<K, V> lastEntry() {

            return safeEntry(table.size() - 1);

      }

      /**

      * Returns the entry with least key greater than or equal to given key (or

      * null if no such key exists).

      *

      * @return entry with least key greater than or equal to given (or null if

      *         no such entry)

      * @throws IllegalArgumentException

      *             if the key is not compatible with the map

      */

      @Override

      public Entry<K, V> ceilingEntry(K key) throws IllegalArgumentException {

            return safeEntry(findIndex(key));

      }

      /**

      * Returns the entry with greatest key less than or equal to given key (or

      * null if no such key exists).

      *

      * @return entry with greatest key less than or equal to given (or null if

      *         no such entry)

      * @throws IllegalArgumentException

      *             if the key is not compatible with the map

      */

      @Override

      public Entry<K, V> floorEntry(K key) throws IllegalArgumentException {

            int j = findIndex(key);

            if (j == size() || !key.equals(table.get(j).getKey()))

                  j--; // look one earlier (unless we had found a perfect match)

            return safeEntry(j);

      }

      /**

      * Returns the entry with greatest key strictly less than given key (or null

      * if no such key exists).

      *

      * @return entry with greatest key strictly less than given (or null if no

      *         such entry)

      * @throws IllegalArgumentException

      *             if the key is not compatible with the map

      */

      @Override

      public Entry<K, V> lowerEntry(K key) throws IllegalArgumentException {

            return safeEntry(findIndex(key) - 1); // go strictly before the ceiling

                                                                         // entry

      }

      /**

      * Returns the entry with least key strictly greater than given key (or null

      * if no such key exists).

      *

      * @return entry with least key strictly greater than given (or null if no

      *         such entry)

      * @throws IllegalArgumentException

      *             if the key is not compatible with the map

      */

      @Override

      public Entry<K, V> higherEntry(K key) throws IllegalArgumentException {

            int j = findIndex(key);

            if (j < size() && key.equals(table.get(j).getKey()))

                  j++; // go past exact match

            return safeEntry(j);

      }

      // support for snapshot iterators for entrySet() and subMap() follow

      private Iterable<Entry<K, V>> snapshot(int startIndex, K stop) {

            ArrayList<Entry<K, V>> buffer = new ArrayList<Entry<K, V>>();

            int j = startIndex;

            while (j < table.size()

                        && (stop == null || compare(stop, table.get(j)) > 0))

                  buffer.add(table.get(j++));

            return buffer;

      }

      /**

      * Returns an iterable collection of all key-value entries of the map.

      *

      * @return iterable collection of the map's entries

      */

      @Override

      public Iterable<Entry<K, V>> entrySet() {

            return snapshot(0, null);

      }

      /**

      * Returns an iterable containing all keys in the range from

      * <code>fromKey</code> inclusive to <code>toKey</code> exclusive.

      *

      * @return iterable with keys in desired range

      * @throws IllegalArgumentException

      *             if <code>fromKey</code> or <code>toKey</code> is not

      *             compatible with the map

      */

      @Override

      public Iterable<Entry<K, V>> subMap(K fromKey, K toKey)

                  throws IllegalArgumentException {

            return snapshot(findIndex(fromKey), toKey);

      }

      /**

      * method to check if a key exists on the table

      *

      * @param key

      *            key to be searched

      * @return true if exists, else false

      */

      public boolean containKey(K key) {

            // finding index of key

            int index = findIndex(key);

            // if index is table size, that means the key is not found yet

            if (index == table.size()) {

                  // does not exist

                  return false;

            }

            // otherwise, the key exists somewhere

            return true;

      }

}

//Test.java (to test the new method)

public class Test {

      public static void main(String[] args) {

            // creating a map

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

            // getting value with key 123, should be null because there is no key

            // 123 on the map

            System.out.println("map.get(123): " + map.get(123));

            // testing the containKey method to see if 123 exists, should be false

            System.out.println("map.containKey(123): " + map.containKey(123));

            // now adding a key 123 with value null

            map.put(123, null);

            // getting value with key 123, should be null not because the value is

            // not there, but the value is added as null

            System.out.println("map.get(123): " + map.get(123));

            // we can ensure that the key exists using containKey method again. this

            // time it should display true

            System.out.println("map.containKey(123): " + map.containKey(123));

      }

}

/*OUTPUT*/

map.get(123): null

map.containKey(123): false

map.get(123): null

map.containKey(123): true

Add a comment
Know the answer?
Add Answer to:
The use of null values in a map is problematic, as there is then no way to differentiate whether ...
Your Answer:

Post as a guest

Your Name:

What's your source?

Earn Coins

Coins can be redeemed for fabulous gifts.

Not the answer you're looking for? Ask your own homework help question. Our experts will answer your question WITHIN MINUTES for Free.
Similar Homework Help Questions
ADVERTISEMENT
Free Homework Help App
Download From Google Play
Scan Your Homework
to Get Instant Free Answers
Need Online Homework Help?
Ask a Question
Get Answers For Free
Most questions answered within 3 hours.
ADVERTISEMENT
ADVERTISEMENT