blob: 5b5422fcf500c0fd78de3f9b34ddc4abf772a7c3 [file] [log] [blame]
package org.apache.maven.surefire.api.util.internal;
/*
* 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.
*/
import java.util.AbstractMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import static java.util.Collections.unmodifiableSet;
/**
* Copies input map in {@link #ImmutableMap(Map) constructor}, and Entries are linked and thread-safe.
* The map is immutable with linear list of entries.
*
* @param <K> key
* @param <V> value
* @since 2.20
*/
public final class ImmutableMap<K, V>
extends AbstractMap<K, V>
{
private final Node<K, V> first;
public ImmutableMap( Map<K, V> map )
{
Node<K, V> first = null;
Node<K, V> previous = null;
for ( Entry<K, V> e : map.entrySet() )
{
Node<K, V> node = new Node<>( e.getKey(), e.getValue() );
if ( first == null )
{
first = node;
}
else
{
previous.next = node;
}
previous = node;
}
this.first = first;
}
@Override
public Set<Entry<K, V>> entrySet()
{
Set<Entry<K, V>> entries = new LinkedHashSet<>();
Node<K, V> node = first;
while ( node != null )
{
entries.add( node );
node = node.next;
}
return unmodifiableSet( entries );
}
static final class Node<K, V>
implements Entry<K, V>
{
final K key;
final V value;
volatile Node<K, V> next;
Node( K key, V value )
{
this.key = key;
this.value = value;
}
@Override
public K getKey()
{
return key;
}
@Override
public V getValue()
{
return value;
}
@Override
public V setValue( V value )
{
throw new UnsupportedOperationException();
}
@Override
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
if ( o == null || getClass() != o.getClass() )
{
return false;
}
Node<?, ?> node = (Node<?, ?>) o;
return getKey() != null ? getKey().equals( node.getKey() ) : node.getKey() == null
&& getValue() != null ? getValue().equals( node.getValue() ) : node.getValue() == null;
}
@Override
public int hashCode()
{
int result = getKey() != null ? getKey().hashCode() : 0;
result = 31 * result + ( getValue() != null ? getValue().hashCode() : 0 );
return result;
}
}
}