/*
 * Copyright (C) 2012 - present by Yann Le Tallec.
 * Please see distribution for license.
 */
package com.assylias.jbloomberg;

import com.bloomberglp.blpapi.CorrelationID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * An immutable, thread safe class that holds a pair of CorrelationID and RealtimeField to uniquely identify
 * subscription data. The factory method provided guarantees uniqueness so that == and equals will always return the
 * same result.
 */
final class EventsKey {

    private final static ConcurrentMap<EventsKey, EventsKey> keys = new ConcurrentHashMap<>();
    private final CorrelationID id;
    private final RealtimeField field;
    private final int hash;

    /**
     * Factory method to ensure that there is only one EventsKey instance associated with a given correlation ID and a
     * field.
     */
    public static EventsKey of(CorrelationID id, RealtimeField field) {
        EventsKey key = new EventsKey(id, field);
        EventsKey previous = keys.putIfAbsent(key, key);
        return previous != null ? previous : key;
    }

    private EventsKey(CorrelationID id, RealtimeField field) {
        this.id = id;
        this.field = field;
        this.hash = getHashCode(id, field); //cached
    }

    @Override
    public int hashCode() {
        return hash;
    }

    /**
     * Assumes that obj is of the right type and is not null
     */
    @Override
    public boolean equals(Object obj) {
        final EventsKey other = (EventsKey) obj;
        if (!this.id.equals(other.id)) {
            return false;
        }
        if (this.field != other.field) {
            return false;
        }
        return true;
    }

    private int getHashCode(CorrelationID id, RealtimeField field) {
        int hash = 7;
        hash = 89 * hash + id.hashCode();
        hash = 89 * hash + field.hashCode();
        return hash;
    }

    @Override
    public String toString() {
        return "key [id=" + id + ", field=" + field + ", hash=" + hash + "]";
    }
}

@@ -177,16 +177,43 @@
 ionID;%0D%0A
+import java.util.Objects;%0D%0A
 import j
@@ -295,16 +295,53 @@
 entMap;%0D
+%0Aimport java.util.function.Function;%0D
 %0A%0D%0A/**%0D%0A
@@ -1059,157 +1059,82 @@
     
-EventsKey key = new EventsKey(id, field);%0D%0A        EventsKey previous = keys.putIfAbsent(key, key);%0D%0A        return previous != null ? previous : key
+return keys.computeIfAbsent(new EventsKey(id, field), Function.identity())
 ;%0D%0A 
@@ -1403,582 +1403,404 @@
     
-/**%0D%0A     * Assumes that obj is of the right type and is not null%0D%0A     */%0D%0A    @Override%0D%0A    public boolean equals(Object obj) %7B%0D%0A        final EventsKey other = (EventsKey) obj;%0D%0A        if (!this.id.equals(other.id)) %7B%0D%0A            return false;%0D%0A        %7D%0D%0A        if (this.field != other.field) %7B%0D%0A            return false;%0D%0A        %7D%0D%0A        return true;%0D%0A    %7D%0D%0A%0D%0A    private int getHashCode(CorrelationID id, RealtimeField field) %7B%0D%0A        int hash = 7;%0D%0A        hash = 89 * hash + id.hashCode();%0D%0A        hash = 89 * hash + field.hashCode();%0D%0A        return hash
+@Override%0D%0A    public boolean equals(Object obj) %7B%0D%0A        if (obj == null) return false;%0D%0A        if (getClass() != obj.getClass()) return false;%0D%0A        final EventsKey other = (EventsKey) obj;%0D%0A        return Objects.equals(this.id, other.id) && this.field == other.field;%0D%0A    %7D%0D%0A%0D%0A    private int getHashCode(CorrelationID id, RealtimeField field) %7B%0D%0A        return Objects.hash(id, field)
 ;%0D%0A 

Simplify code in EventsKey