001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4.keyvalue; 018 019import java.io.Serializable; 020import java.util.Map; 021import java.util.Map.Entry; 022import java.util.Objects; 023 024import org.apache.commons.collections4.KeyValue; 025 026/** 027 * A {@link Entry Map.Entry} tied to a map underneath. 028 * <p> 029 * This can be used to enable a map entry to make changes on the underlying 030 * map, however this will probably mess up any iterators. 031 * </p> 032 * 033 * @param <K> The type of keys 034 * @param <V> The type of mapped values 035 * @since 3.0 036 */ 037public class TiedMapEntry<K, V> implements Map.Entry<K, V>, KeyValue<K, V>, Serializable { 038 039 /** Serialization version */ 040 private static final long serialVersionUID = -8453869361373831205L; 041 042 /** The map underlying the entry/iterator */ 043 private final Map<K, V> map; 044 045 /** The key */ 046 private final K key; 047 048 /** 049 * Constructs a new entry with the given Map and key. 050 * 051 * @param map The map 052 * @param key The key 053 */ 054 public TiedMapEntry(final Map<K, V> map, final K key) { 055 this.map = map; 056 this.key = key; 057 } 058 059 /** 060 * Compares this {@code Map.Entry} with another {@code Map.Entry}. 061 * <p> 062 * Implemented per API documentation of {@link java.util.Map.Entry#equals(Object)} 063 * 064 * @param obj The object to compare to 065 * @return true if equal key and value 066 */ 067 @Override 068 public boolean equals(final Object obj) { 069 if (obj == this) { 070 return true; 071 } 072 if (!(obj instanceof Map.Entry)) { 073 return false; 074 } 075 final Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj; 076 return 077 Objects.equals(key, other.getKey()) && 078 Objects.equals(getValue(), other.getValue()); 079 } 080 081 /** 082 * Gets the key of this entry 083 * 084 * @return The key 085 */ 086 @Override 087 public K getKey() { 088 return key; 089 } 090 091 /** 092 * Gets the value of this entry direct from the map. 093 * 094 * @return The value 095 */ 096 @Override 097 public V getValue() { 098 return map.get(key); 099 } 100 101 /** 102 * Gets a hashCode compatible with the equals method. 103 * <p> 104 * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()} 105 * 106 * @return A suitable hash code 107 */ 108 @Override 109 public int hashCode() { 110 final Object value = getValue(); 111 return (getKey() == null ? 0 : getKey().hashCode()) ^ 112 (value == null ? 0 : value.hashCode()); 113 } 114 115 /** 116 * Sets the value associated with the key direct onto the map. 117 * 118 * @param value The new value 119 * @return The old value 120 * @throws IllegalArgumentException if the value is set to this map entry 121 */ 122 @Override 123 public V setValue(final V value) { 124 if (value == this) { 125 throw new IllegalArgumentException("Cannot set value to this map entry"); 126 } 127 return map.put(key, value); 128 } 129 130 /** 131 * Gets a string version of the entry. 132 * 133 * @return entry as a string 134 */ 135 @Override 136 public String toString() { 137 return getKey() + "=" + getValue(); 138 } 139 140}