//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

A multi valued Map.
Type parameters:
  • <V> – the entry type for multimap values
/** * A multi valued Map. * * @param <V> the entry type for multimap values */
@SuppressWarnings("serial") public class MultiMap<V> extends HashMap<String, List<V>> { public MultiMap() { super(); } public MultiMap(Map<String, List<V>> map) { super(map); } public MultiMap(MultiMap<V> map) { super(map); }
Get multiple values. Single valued entries are converted to singleton lists.
Params:
  • name – The entry key.
Returns:Unmodifieable List of values.
/** * Get multiple values. * Single valued entries are converted to singleton lists. * * @param name The entry key. * @return Unmodifieable List of values. */
public List<V> getValues(String name) { List<V> vals = super.get(name); if ((vals == null) || vals.isEmpty()) { return null; } return vals; }
Get a value from a multiple value. If the value is not a multivalue, then index 0 retrieves the value or null.
Params:
  • name – The entry key.
  • i – Index of element to get.
Returns:Unmodifieable List of values.
/** * Get a value from a multiple value. * If the value is not a multivalue, then index 0 retrieves the * value or null. * * @param name The entry key. * @param i Index of element to get. * @return Unmodifieable List of values. */
public V getValue(String name, int i) { List<V> vals = getValues(name); if (vals == null) { return null; } if (i == 0 && vals.isEmpty()) { return null; } return vals.get(i); }
Get value as String. Single valued items are converted to a String with the toString() Object method. Multi valued entries are converted to a comma separated List. No quoting of commas within values is performed.
Params:
  • name – The entry key.
Returns:String value.
/** * Get value as String. * Single valued items are converted to a String with the toString() * Object method. Multi valued entries are converted to a comma separated * List. No quoting of commas within values is performed. * * @param name The entry key. * @return String value. */
public String getString(String name) { List<V> vals = get(name); if ((vals == null) || (vals.isEmpty())) { return null; } if (vals.size() == 1) { // simple form. return vals.get(0).toString(); } // delimited form StringBuilder values = new StringBuilder(128); for (V e : vals) { if (e != null) { if (values.length() > 0) values.append(','); values.append(e.toString()); } } return values.toString(); }
Put multi valued entry.
Params:
  • name – The entry key.
  • value – The simple value
Returns:The previous value or null.
/** * Put multi valued entry. * * @param name The entry key. * @param value The simple value * @return The previous value or null. */
public List<V> put(String name, V value) { if (value == null) { return super.put(name, null); } List<V> vals = new ArrayList<>(); vals.add(value); return put(name, vals); }
Shorthand version of putAll
Params:
  • input – the input map
/** * Shorthand version of putAll * * @param input the input map */
public void putAllValues(Map<String, V> input) { for (Map.Entry<String, V> entry : input.entrySet()) { put(entry.getKey(), entry.getValue()); } }
Put multi valued entry.
Params:
  • name – The entry key.
  • values – The List of multiple values.
Returns:The previous value or null.
/** * Put multi valued entry. * * @param name The entry key. * @param values The List of multiple values. * @return The previous value or null. */
public List<V> putValues(String name, List<V> values) { return super.put(name, values); }
Put multi valued entry.
Params:
  • name – The entry key.
  • values – The array of multiple values.
Returns:The previous value or null.
/** * Put multi valued entry. * * @param name The entry key. * @param values The array of multiple values. * @return The previous value or null. */
@SafeVarargs public final List<V> putValues(String name, V... values) { List<V> list = new ArrayList<>(); list.addAll(Arrays.asList(values)); return super.put(name, list); }
Add value to multi valued entry. If the entry is single valued, it is converted to the first value of a multi valued entry.
Params:
  • name – The entry key.
  • value – The entry value.
/** * Add value to multi valued entry. * If the entry is single valued, it is converted to the first * value of a multi valued entry. * * @param name The entry key. * @param value The entry value. */
public void add(String name, V value) { List<V> lo = get(name); if (lo == null) { lo = new ArrayList<>(); } lo.add(value); super.put(name, lo); }
Add values to multi valued entry. If the entry is single valued, it is converted to the first value of a multi valued entry.
Params:
  • name – The entry key.
  • values – The List of multiple values.
/** * Add values to multi valued entry. * If the entry is single valued, it is converted to the first * value of a multi valued entry. * * @param name The entry key. * @param values The List of multiple values. */
public void addValues(String name, List<V> values) { List<V> lo = get(name); if (lo == null) { lo = new ArrayList<>(); } lo.addAll(values); put(name, lo); }
Add values to multi valued entry. If the entry is single valued, it is converted to the first value of a multi valued entry.
Params:
  • name – The entry key.
  • values – The String array of multiple values.
/** * Add values to multi valued entry. * If the entry is single valued, it is converted to the first * value of a multi valued entry. * * @param name The entry key. * @param values The String array of multiple values. */
public void addValues(String name, V[] values) { List<V> lo = get(name); if (lo == null) { lo = new ArrayList<>(); } lo.addAll(Arrays.asList(values)); put(name, lo); }
Merge values.
Params:
  • map – the map to overlay on top of this one, merging together values if needed.
Returns:true if an existing key was merged with potentially new values, false if either no change was made, or there were only new keys.
/** * Merge values. * * @param map the map to overlay on top of this one, merging together values if needed. * @return true if an existing key was merged with potentially new values, false if either no change was made, or there were only new keys. */
public boolean addAllValues(MultiMap<V> map) { boolean merged = false; if ((map == null) || (map.isEmpty())) { // done return merged; } for (Map.Entry<String, List<V>> entry : map.entrySet()) { String name = entry.getKey(); List<V> values = entry.getValue(); if (this.containsKey(name)) { merged = true; } this.addValues(name, values); } return merged; }
Remove value.
Params:
  • name – The entry key.
  • value – The entry value.
Returns:true if it was removed.
/** * Remove value. * * @param name The entry key. * @param value The entry value. * @return true if it was removed. */
public boolean removeValue(String name, V value) { List<V> lo = get(name); if ((lo == null) || (lo.isEmpty())) { return false; } boolean ret = lo.remove(value); if (lo.isEmpty()) { remove(name); } else { put(name, lo); } return ret; }
Test for a specific single value in the map.

NOTE: This is a SLOW operation, and is actively discouraged.

Params:
  • value – the value to search for
Returns:true if contains simple value
/** * Test for a specific single value in the map. * <p> * NOTE: This is a SLOW operation, and is actively discouraged. * * @param value the value to search for * @return true if contains simple value */
public boolean containsSimpleValue(V value) { for (List<V> vals : values()) { if ((vals.size() == 1) && vals.contains(value)) { return true; } } return false; } @Override public String toString() { Iterator<Entry<String, List<V>>> iter = entrySet().iterator(); StringBuilder sb = new StringBuilder(); sb.append('{'); boolean delim = false; while (iter.hasNext()) { Entry<String, List<V>> e = iter.next(); if (delim) { sb.append(", "); } String key = e.getKey(); List<V> vals = e.getValue(); sb.append(key); sb.append('='); if (vals.size() == 1) { sb.append(vals.get(0)); } else { sb.append(vals); } delim = true; } sb.append('}'); return sb.toString(); }
Returns:Map of String arrays
/** * @return Map of String arrays */
public Map<String, String[]> toStringArrayMap() { HashMap<String, String[]> map = new HashMap<String, String[]>(size() * 3 / 2) { @Override public String toString() { StringBuilder b = new StringBuilder(); b.append('{'); for (String k : super.keySet()) { if (b.length() > 1) b.append(','); b.append(k); b.append('='); b.append(Arrays.asList(super.get(k))); } b.append('}'); return b.toString(); } }; for (Map.Entry<String, List<V>> entry : entrySet()) { String[] a = null; if (entry.getValue() != null) { a = new String[entry.getValue().size()]; a = entry.getValue().toArray(a); } map.put(entry.getKey(), a); } return map; } }