Implementation of KeyEventDispatcher in Java
First...
I'd, personally, rely on the virtual key code over the key character.  It's possible that the key character may not have been interpreted  until the KEY_TYPED event (or at least I remember some issue where the char could be interpreted at certain stages)
private HashMap&lt;Integer, Boolean&gt; keyPresses = new HashMap&lt;&gt;();

@Override
public boolean dispatchKeyEvent(KeyEvent e) {
    int keyCode = e.getKeyCode();

    if (e.getID() == KeyEvent.KEY_PRESSED) {

        if (keyPresses.contains(keyCode) &amp;&amp; keyPresses.get(keyCode).booleanValue()) {
            return false;
        }
        keyPresses.put(keyCode, new Boolean(true));

This also means you don't need to convert the key to lower case, as the virtual key doesn't carry the modifier information (the key character is the key code + the modifiers)
There is a problem with this, KeyEvent.VK_1 can represent both 1 and !, so you might need to consider using KeyStroke instead...
Second...
It's a nitpick on my behalf, but I like a single entry and single exit point in the code...
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
    int keyCode = e.getKeyCode();

    if (e.getID() == KeyEvent.KEY_PRESSED) {

        if (!keyPresses.contains(keyCode) || !keyPresses.get(keyCode).booleanValue()) {
            keyPresses.put(keyCode, new Boolean(true));

It generally makes the code easier to read and the logic to follow as return statements can &quot;hide&quot; in code and it's easy to miss them (IMHO)
Third
Rather than something like this...
switch (keyToLowerCaseIfUpperCase(e.getKeyChar())) {
    case 'a': System.out.println(&quot;D&quot;); break; // these are just two test cases
    case 'b': System.out.println(&quot;E&quot;); break;
    default: break;
}

I would consider using another Map, to map between the virtual key and the value or &quot;callback&quot; you want to call.  It will be easier to add new values and reuse the code
I'd also consider using a callback mechanism, which would notify of the KEY_PRESSED and KEY_RELEASED events, so the dispatcher didn't do the conversion itself, but simply managed the notification processes, further separating the implementation logic and allow the dispatcher to be more reusable.
You could achieve the same thing through abstraction, but I think some kind of Observer Pattern would be more pratical (IMHO)
Fourth
Unless you really need to know if a key is not been pressed, I would remove the keyCode from the Map on the KEY_RELEASED event
} else if (e.getID() == KeyEvent.KEY_RELEASED){
    keyPresses.remove(keyCode);
}

As it would simpler to just use something like keyPresses.contains(keyCode) instead of then actually needing to check the value associated with, but this comes down to needs.
You could replace the Map with a Set instead which would be simpler, either the keyCode exists or it doesn't...