/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hashtable; /** * Fixed size hashtable with CuckooHashing collision resolution. Not fully * functional - does not do rehashing, and may remove already present elements * when putting a new element. * * @author tomasz * */ public class CuckooHash implements THashSet { private final int shiftAttempts = 100; private int hash_mask; private Long[] entries; private int failed; public CuckooHash(int size) { entries = new Long[size]; hash_mask = size - 1; } public Long get(Long id) { if (entries[getHash1(id)].equals(id)) return id; if (entries[getHash2(id)].equals(id)) return id; return null; } public Long put(Long id) { int n = 0; long originalId = id; int pos = getHash1(id); if ((entries[pos] == null) || (entries[pos].equals(id))) { entries[pos] = id; return id; } int pos2 = getHash1(id); if ((entries[pos2] == null) || (entries[pos2].equals(id))) { entries[pos2] = id; return id; } while (n < shiftAttempts) { if (entries[pos] == null) { entries[pos] = id; return originalId; } Long temp = entries[pos]; entries[pos] = id; id = temp; n++; int hash1 = getHash1(id); if (pos == hash1) { pos = getHash2(id); } else { pos = hash1; } } // when "put" fails it expells a previously present element // this implementation is only for testing purposes failed++; return id; } public int getFailed() { return failed; } public Long remove(Long id) { if (entries[getHash1(id)].equals(id)) { entries[getHash1(id)] = null; return id; } if (entries[getHash2(id)].equals(id)) { entries[getHash2(id)] = null; return id; } return null; } private int getHash1(long id) { return Hashes.getHash(id, 0) & hash_mask; } private int getHash2(long id) { return Hashes.getHash(id, 1) & hash_mask; } }