1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.collections4.keyvalue;
18
19 import java.io.Serializable;
20 import java.util.Map;
21 import java.util.Objects;
22
23 import org.apache.commons.collections4.KeyValue;
24
25 /**
26 * A {@link java.util.Map.Entry Map.Entry} tied to a map underneath.
27 * <p>
28 * This can be used to enable a map entry to make changes on the underlying
29 * map, however this will probably mess up any iterators.
30 * </p>
31 *
32 * @param <K> the type of keys
33 * @param <V> the type of mapped values
34 * @since 3.0
35 */
36 public class TiedMapEntry<K, V> implements Map.Entry<K, V>, KeyValue<K, V>, Serializable {
37
38 /** Serialization version */
39 private static final long serialVersionUID = -8453869361373831205L;
40
41 /** The map underlying the entry/iterator */
42 private final Map<K, V> map;
43
44 /** The key */
45 private final K key;
46
47 /**
48 * Constructs a new entry with the given Map and key.
49 *
50 * @param map the map
51 * @param key the key
52 */
53 public TiedMapEntry(final Map<K, V> map, final K key) {
54 this.map = map;
55 this.key = key;
56 }
57
58 /**
59 * Compares this {@code Map.Entry} with another {@code Map.Entry}.
60 * <p>
61 * Implemented per API documentation of {@link java.util.Map.Entry#equals(Object)}
62 *
63 * @param obj the object to compare to
64 * @return true if equal key and value
65 */
66 @Override
67 public boolean equals(final Object obj) {
68 if (obj == this) {
69 return true;
70 }
71 if (!(obj instanceof Map.Entry)) {
72 return false;
73 }
74 final Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj;
75 return
76 Objects.equals(key, other.getKey()) &&
77 Objects.equals(getValue(), other.getValue());
78 }
79
80 /**
81 * Gets the key of this entry
82 *
83 * @return the key
84 */
85 @Override
86 public K getKey() {
87 return key;
88 }
89
90 /**
91 * Gets the value of this entry direct from the map.
92 *
93 * @return the value
94 */
95 @Override
96 public V getValue() {
97 return map.get(key);
98 }
99
100 /**
101 * Gets a hashCode compatible with the equals method.
102 * <p>
103 * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()}
104 *
105 * @return a suitable hash code
106 */
107 @Override
108 public int hashCode() {
109 final Object value = getValue();
110 return (getKey() == null ? 0 : getKey().hashCode()) ^
111 (value == null ? 0 : value.hashCode());
112 }
113
114 /**
115 * Sets the value associated with the key direct onto the map.
116 *
117 * @param value the new value
118 * @return the old value
119 * @throws IllegalArgumentException if the value is set to this map entry
120 */
121 @Override
122 public V setValue(final V value) {
123 if (value == this) {
124 throw new IllegalArgumentException("Cannot set value to this map entry");
125 }
126 return map.put(key, value);
127 }
128
129 /**
130 * Gets a string version of the entry.
131 *
132 * @return entry as a string
133 */
134 @Override
135 public String toString() {
136 return getKey() + "=" + getValue();
137 }
138
139 }