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 * https://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.util.Map;
20 import java.util.Map.Entry;
21 import java.util.Objects;
22
23 import org.apache.commons.collections4.KeyValue;
24
25 /**
26 * A mutable {@code KeyValue} pair that does not implement
27 * {@link Entry Map.Entry}.
28 * <p>
29 * Note that a {@code DefaultKeyValue} instance may not contain
30 * itself as a key or value.
31 * </p>
32 *
33 * @param <K> The type of keys
34 * @param <V> The type of values
35 * @since 3.0
36 */
37 public class DefaultKeyValue<K, V> extends AbstractKeyValue<K, V> {
38
39 /**
40 * Constructs a new pair with a null key and null value.
41 */
42 public DefaultKeyValue() {
43 super(null, null);
44 }
45
46 /**
47 * Constructs a new pair with the specified key and given value.
48 *
49 * @param key The key for the entry, may be null
50 * @param value The value for the entry, may be null
51 */
52 public DefaultKeyValue(final K key, final V value) {
53 super(key, value);
54 }
55
56 /**
57 * Constructs a new pair from the specified {@code KeyValue}.
58 *
59 * @param pair The pair to copy, must not be null
60 * @throws NullPointerException if the entry is null
61 */
62 public DefaultKeyValue(final KeyValue<? extends K, ? extends V> pair) {
63 super(pair.getKey(), pair.getValue());
64 }
65
66 /**
67 * Constructs a new pair from the specified {@code Map.Entry}.
68 *
69 * @param entry The entry to copy, must not be null
70 * @throws NullPointerException if the entry is null
71 */
72 public DefaultKeyValue(final Map.Entry<? extends K, ? extends V> entry) {
73 super(entry.getKey(), entry.getValue());
74 }
75
76 /**
77 * Compares this {@code Map.Entry} with another {@code Map.Entry}.
78 * <p>
79 * Returns true if the compared object is also a {@code DefaultKeyValue},
80 * and its key and value are equal to this object's key and value.
81 *
82 * @param obj The object to compare to
83 * @return true if equal key and value
84 */
85 @Override
86 public boolean equals(final Object obj) {
87 if (obj == this) {
88 return true;
89 }
90 if (!(obj instanceof DefaultKeyValue)) {
91 return false;
92 }
93
94 final DefaultKeyValue<?, ?> other = (DefaultKeyValue<?, ?>) obj;
95 return
96 Objects.equals(getKey(), other.getKey()) &&
97 Objects.equals(getValue(), other.getValue());
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 * however subclasses may override this.
105 *
106 * @return A suitable hash code
107 */
108 @Override
109 public int hashCode() {
110 return (getKey() == null ? 0 : getKey().hashCode()) ^
111 (getValue() == null ? 0 : getValue().hashCode());
112 }
113
114 /**
115 * Sets the key.
116 *
117 * @param key The new key
118 * @return The old key
119 * @throws IllegalArgumentException if key is this object
120 */
121 @Override
122 public K setKey(final K key) {
123 if (key == this) {
124 throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a key.");
125 }
126
127 return super.setKey(key);
128 }
129
130 /**
131 * Sets the value.
132 *
133 * @return The old value of the value
134 * @param value The new value
135 * @throws IllegalArgumentException if value is this object
136 */
137 @Override
138 public V setValue(final V value) {
139 if (value == this) {
140 throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a value.");
141 }
142
143 return super.setValue(value);
144 }
145
146 /**
147 * Returns a new {@code Map.Entry} object with key and value from this pair.
148 *
149 * @return A MapEntry instance
150 */
151 public Map.Entry<K, V> toMapEntry() {
152 return new DefaultMapEntry<>(this);
153 }
154
155 }