Use Java 8 streams to transform a Map with nulls

Use Collect:

final Function<String, String> fn= str -> str == null ? null : str.toLowerCase();
Map<String, String> copy = headers.entrySet().stream()
   .collect(HashMap::new,
            (m, e) -> m.put(fn.apply(e.getKey()), fn.apply(e.getValue())), 
            Map::putAll);

Or with AbacusUtil

Map<String, String> copy = Stream.of(headers)
   .collect(HashMap::new, 
     (m, e) -> m.put(N.toLowerCase(e.getKey()), N.toLowerCase(e.getValue())));

updated on 2/4, Or:

Map<String, String> copy = EntryStream.of(headers)
   .toMap(entry -> N.toLowerCase(entry.getKey()), entry -> N.toLowerCase(entry.getValue()));

You cannot use Collectors.toMap() without getting a NPE since you have a null value present in your map, as explained by @dkatzel already, but I still wanted to use Stream API;

Map<String, String> headers = new HashMap<>();
headers.put("good", "AsDf");
headers.put("SomE", "GreETing");
headers.put("HELLO", null);
headers.put(null, "WOrLd");

new HashSet<>(headers.entrySet()).stream()
    .peek(entry -> entry.setValue(Objects.isNull(entry.getValue()) ? null : entry.getValue().toLowerCase()))
    .filter(entry -> !Objects.isNull(entry.getKey()) && !entry.getKey().equals(entry.getKey().toLowerCase()))
    .forEach(entry -> {
        headers.put(entry.getKey().toLowerCase(), entry.getValue());
        headers.remove(entry.getKey());
    });

System.out.println(headers);

Prints out;

{null=world, some=greeting, hello=null, good=asdf}

The problem is toMap() invokes the underlying Map implementation being built's merge() function which does not allow values to be null

from the javadoc for Map#merge (emphasis mine)

If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value. Otherwise, replaces the associated value with the results of the given remapping function, or removes if the result is null.

So using Collectors.toMap() will not work.

You can do this without stream just fine:

Map<String,String> copy = new HashMap<>();

for(Entry<String, String> entry : headers.entrySet()){
    copy.put(entry.getKey() !=null ? entry.getKey().toLowerCase() : null, 
             entry.getValue() !=null ? entry.getValue().toLowerCase() : null
            );
}