net.sf.jasperreports.engine.util.LinkedMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
package net.sf.jasperreports.engine.util;
import java.util.HashMap;
import java.util.Map;
/**
* A doubly linked list that can also map entries on keys.
*
* The list can be iterated in FIFO order and implements the following operations
* in constant time:
*
* - adding an element at the start
* - adding an element at the end
* - finding and removing an element based on a key
*
*
* @author Lucian Chirita ([email protected])
*/
public class LinkedMap
{
protected static class LinkedValue implements Map.Entry
{
private LinkedValue prev;
private LinkedValue next;
private K key;
private V value;
protected LinkedValue(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();
}
}
private final LinkedValue header;
private final HashMap> map;
/**
* Creates a list.
*/
public LinkedMap()
{
map = new HashMap>();
header = new LinkedValue(null, null);
header.prev = header;
header.next = header;
}
/**
* Adds a value at the end of the list.
*
* @param key the not-null key to which the value is mapped
* @param value the value
*/
public void add(K key, V value)
{
if (key != null && map.containsKey(key))
{
//NOP
return;
}
// add last
LinkedValue entry = new LinkedValue(key, value);
entry.prev = header.prev;
entry.next = header;
header.prev.next = entry;
header.prev = entry;
if (key != null)
{
map.put(key, entry);
}
}
/**
* Adds a value at the start of the list
*
* @param key the not-null key to which the value is mapped
* @param value the value
*/
public void addFirst(K key, V value)
{
if (key != null && map.containsKey(key))
{
//NOP
return;
}
// add first
LinkedValue entry = new LinkedValue(key, value);
entry.next = header.next;
entry.prev = header;
header.next.prev = entry;
header.next = entry;
if (key != null)
{
map.put(key, entry);
}
}
/**
* Determines whether the list is empty.
*
* @return whether the list is empty
*/
public boolean isEmpty()
{
return header.next == header;
}
/**
* Removes and returns the first element in the list.
*
* @return the first element in the list
*/
public V pop()
{
LinkedValue entry = removeFirst();
return entry.value;
}
/**
* Removes and returns the first element in the list.
*
* @return the first element in the list
*/
public Map.Entry popEntry()
{
return removeFirst();
}
protected LinkedValue removeFirst()
{
if (header.next == header)
{
throw new IllegalStateException("Empty map");
}
LinkedValue entry = header.next;
entry.prev.next = entry.next;
entry.next.prev = entry.prev;
if (entry.key != null)
{
map.remove(entry.key);
}
return entry;
}
/**
* Removes and returns an element mapped to a key.
*
* @param key
* @return the element mapped to the key, null
if the key is not mapped
*/
public V remove(K key)
{
if (key == null)
{
throw new NullPointerException("Key cannot be null");
}
LinkedValue entry = map.remove(key);
if (entry == null)
{
return null;
}
entry.prev.next = entry.next;
entry.next.prev = entry.prev;
return entry.value;
}
/**
* Adds all entries from the map to this map, preserving the order.
*
* @param map
*/
public void addAll(LinkedMap map)
{
for (LinkedValue entry = map.header.next; entry != map.header; entry = entry.next)
{
add(entry.key, entry.value);
}
}
}