LaVOZs

The World’s Largest Online Community for Developers

'; java - Put in the map if key exists and value is not null, else throw exception - LavOzs.Com

void addToMapIfKeyExists(String k, String v) {
    if (!map.containsKey(k)) {
        throw new NoSuchElementException(k + " does not exist in the map");
    }

    // else ignore
    if (v != null) {
        map.put(k, v);
    }
}

Can I write this in a better way in Java 8? Can I merge it into one expression in some way?

You can, in a single statement:

public void overwrite(String k, String v) {
    map.compute(k, (key, value) -> {
        if (value == null) throw new NoSuchElementException(key + " does not exist in the map");
        return v == null ? value : v;
    });
}

The above does:

[1] if key is not in the map, or is mapped to null, it throws NoSuchElementException.

[2] Otherwise, will do nothing if you're trying to set null.

[3] otherwise, will set the key to the new value

Which is apparently what you want, but that's a bizarre combination of requirements.

In the simplest of the forms, as it reads, the following might suit your needs:

static void addToMapIfKeyExists(String k, String v) {
    if (v != null && map.containsKey(k)) { // if key exists and value is not null
        map.put(k, v); // Put in the map 
    } else { // else throw exception
        throw new IllegalArgumentException("Else throwing exception.");
    }
}

Disclaimer: Decide wisely before choosing this. I would NOT recommend this as a practice based on the APIs involved.

static void addToMapIfKeyExistsOneLiner(String k, String v) {
    map.put(k, Optional.ofNullable(v)
            .filter(ignore -> map.containsKey(k))
            .orElseThrow(IllegalArgumentException::new));
}

and I could compare the behavior of both these methods is the same using the following tests:

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

private static void comparativeTest() {
    map.put("a", "trying");
    map.put("b", "crying");

    addToMapIfKeyExists("a", "works");
    System.out.println(map.get("a").equals("works"));

    addToMapIfKeyExistsOneLiner("a", "works");
    System.out.println(map.get("a").equals("works"));


    addToMapIfKeyExists("b", null); // null value throw exception
    addToMapIfKeyExists("e", "new key throws exception");

    addToMapIfKeyExistsOneLiner("b", null); // null value throw exception
    addToMapIfKeyExistsOneLiner("e", "new key throws exception");
}

Remember, the requirement is:

Put in the map if key exists or value is not null, else throw exception

Which means:

  • If key doesn't exist, throw exception
  • If value is null, throw exception
  • Put in the map

You should do the null check first, then use the replace(K key, V value) method and check the return value, so you only do the map lookup once.

void addToMapIfKeyExists(String k, String v) {
    if (v == null)
        throw new IllegalArgumentException("Value is null");
    if (map.replace(k, v) == null)
        throw new NoSuchElementException("Key doesn't exist: " + k);
}
Related
Most efficient way to increment a Map value in Java
Standard concise way to copy a file in Java?
Sort a Map<Key, Value> by values
Java Hashmap: How to get key from value?
How do I check if a file exists in Java?
How to update a value, given a key in a hashmap?
Java 8 Lambda function that throws exception?
Java 8 NullPointerException in Collectors.toMap