UnmodifiableWrappingMap.java
/*
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2026, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v2.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package ch.qos.logback.core.util;
import java.io.Serializable;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* An unmodifiable view of an existing {@link Map}, in the same spirit as
* {@code Collections.UnmodifiableMap}.
*
* <p>The backing map is not copied. Callers that need a snapshot must pass a
* copy.</p>
*
* @param <K> the type of keys
* @param <V> the type of values
* @author Ceki Gülcü
* @since 1.6.4
*/
public final class UnmodifiableWrappingMap<K, V> extends AbstractMap<K, V> implements Serializable {
private static final long serialVersionUID = 1L;
private final Map<? extends K, ? extends V> m;
private transient Set<Entry<K, V>> entrySet;
public UnmodifiableWrappingMap(Map<? extends K, ? extends V> m) {
if (m == null) {
throw new NullPointerException();
}
this.m = m;
}
@Override
public int size() {
return m.size();
}
@Override
public boolean isEmpty() {
return m.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return m.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return m.containsValue(value);
}
@Override
public V get(Object key) {
return m.get(key);
}
@Override
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public V remove(Object key) {
throw new UnsupportedOperationException();
}
@Override
public void putAll(Map<? extends K, ? extends V> map) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public Set<Entry<K, V>> entrySet() {
if (entrySet == null) {
entrySet = new UnmodifiableEntrySet<>(m.entrySet());
}
return entrySet;
}
@Override
public boolean equals(Object o) {
return o == this || m.equals(o);
}
@Override
public int hashCode() {
return m.hashCode();
}
/**
* Wraps each {@link Entry} so {@link Entry#setValue(Object)} cannot mutate
* the backing map.
*/
private static final class UnmodifiableEntrySet<K, V> extends AbstractSet<Entry<K, V>> {
private final Set<? extends Entry<? extends K, ? extends V>> s;
UnmodifiableEntrySet(Set<? extends Entry<? extends K, ? extends V>> s) {
this.s = s;
}
@Override
public int size() {
return s.size();
}
@Override
public boolean contains(Object o) {
return s.contains(o);
}
@Override
public Iterator<Entry<K, V>> iterator() {
return new Iterator<Entry<K, V>>() {
private final Iterator<? extends Entry<? extends K, ? extends V>> i = s.iterator();
@Override
public boolean hasNext() {
return i.hasNext();
}
@Override
public Entry<K, V> next() {
return new SimpleImmutableEntry<>(i.next());
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
}