001/*
002 * Copyright (c) 2015-2020, Oracle and/or its affiliates. All rights reserved.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.tribuo.util.infotheory.impl;
018
019import com.oracle.labs.mlrg.olcut.util.Pair;
020
021import java.util.ArrayList;
022
023/**
024 * A pair of things with a cached hashcode.
025 * <p>
026 * The cache is calculated on construction, and the objects inside the pair are thus expected to be immutable.
027 * If they aren't then the behaviour is undefined (and you shouldn't use this class).
028 * @param <T1> The type of the first object.
029 * @param <T2> The type of the second object.
030 */
031public class CachedPair<T1, T2> extends Pair<T1,T2> {
032    private static final long serialVersionUID = 1L;
033
034    private final int cachedHash;
035    
036    public CachedPair(T1 a, T2 b) {
037        super(a,b);
038        this.cachedHash = super.hashCode();
039    }
040
041    /**
042     * Takes two arrays and zips them together into an array of CachedPairs.
043     * @param <T1> The type contained in the first array.
044     * @param <T2> The type contained in the second array.
045     * @param first An array of values.
046     * @param second Another array of values.
047     * @return The zipped array.
048     */
049    public static <T1,T2> ArrayList<CachedPair<T1,T2>> zipArraysCached(ArrayList<T1> first, ArrayList<T2> second) {
050        if (first.size() == second.size()) {
051            ArrayList<CachedPair<T1,T2>> output = new ArrayList<>(first.size());
052
053            for (int i = 0; i < first.size(); i++) {
054                CachedPair<T1,T2> pair = new CachedPair<>(first.get(i),second.get(i));
055                output.add(i, pair);
056            }
057
058            return output;
059        } else {
060            throw new IllegalArgumentException("Zipping requires arrays of the same length. first.size() = " + first.size() + ", second.size() = " + second.size());
061        }
062    }
063
064    /**
065     * Overridden hashcode.
066     * Uses the cached value calculated on construction.
067     * @return A 32-bit integer.
068     */
069    @Override
070    public int hashCode() {
071        return cachedHash;
072    }
073
074    @Override
075    public boolean equals(Object o) {
076        if (this == o) return true;
077        if (o == null || getClass() != o.getClass()) return false;
078        if (!super.equals(o)) return false;
079        CachedPair<?, ?> that = (CachedPair<?, ?>) o;
080        return cachedHash == that.cachedHash;
081    }
082}