/*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* This class is used to show how you can sort a java.uti.Map for values. This also takes care of null and duplicate
* values present in the map.
*/
@SuppressWarnings("unchecked")
public class ValueSortMap
{
public Map<Integer, Integer> sortThis(Map<Integer, Integer> map, boolean asc)
{
return sortMapByValue(map, asc);
}
/**
* This method returns the new LinkedHashMap sorted with values for passed Comparater. If null values exist they
* will be put in the last of the returned LinkedHashMap. If there are duplicate values they will come together at
* the values ordering order but ordering between same multiple values is ramdom. Passed Map will be intect.
*
* @param inMap Map to be sorted
* @param comparator Values will be sorted as per passed Comparater
* @return LinkedHashMap Sorted new LinkedHashMap
*/
@SuppressWarnings("rawtypes")
public static LinkedHashMap sortMapByValue(Map inMap, Comparator comparator)
{
return sortMapByValue(inMap, comparator, null);
}
/**
* This method returns the new LinkedHashMap sorted with values for passed ascendingOrder. If null values exist they
* will be put in the last for true value of ascendingOrder or will be put on top of the returned LinkedHashMap for
* false value of ascendingOrder. If there are duplicate values they will come together at the values ordering order
* but ordering between same multiple values is ramdom. Passed Map will be intect.
*
* @param inMap Map to be sorted
* @param ascendingOrder Values will be sorted as per value of ascendingOrder
* @return LinkedHashMap Sorted new LinkedHashMap
*/
@SuppressWarnings("rawtypes")
public static LinkedHashMap sortMapByValue(Map inMap, boolean ascendingOrder)
{
return sortMapByValue(inMap, null, ascendingOrder);
}
/**
* This method returns the new LinkedHashMap sorted with values in ascending order. If null values exist they will
* be put in the last of the returned LinkedHashMap. If there are duplicate values they will come together at the
* values ordering order but ordering between same multiple values is ramdom. Passed Map will be intect.
*
* @param inMap Map to be sorted
* @return LinkedHashMap Sorted new LinkedHashMap
*/
@SuppressWarnings("rawtypes")
public static LinkedHashMap sortMapByValue(Map inMap)
{
return sortMapByValue(inMap, null, null);
}
/**
* This method returns the new LinkedHashMap sorted with values. Values will be sorted as value of passed comparator
* if ascendingOrder is null or in order of passed ascendingOrder if it is not null. If null values exist they will
* be put in the last for true value of ascendingOrder or will be put on top of the returned LinkedHashMap for false
* value of ascendingOrder. If there are duplicate values they will come together at the values ordering order but
* ordering between same multiple values is ramdom. Passed Map will be intect.
*
* @param inMap Map to be sorted
* @param comparator Values will be sorted as per passed Comparater
* @param ascendingOrder Values will be sorted as per value of ascendingOrder
* @return LinkedHashMap Sorted new LinkedHashMap
*/
@SuppressWarnings("rawtypes")
private static LinkedHashMap sortMapByValue(Map inMap, Comparator comparator, Boolean ascendingOrder)
{
int iSize = inMap.size();
// Create new LinkedHashMap that need to be returned
LinkedHashMap sortedMap = new LinkedHashMap(iSize);
Collection values = inMap.values();
ArrayList valueList = new ArrayList(values); // To get List of all values in passed Map
HashSet distinctValues = new HashSet(values); // To know the distinct values in passed Map
// Do handing for null values. remove them from the list that will be used for sorting
int iNullValueCount = 0; // Total number of null values present in passed Map
if (distinctValues.contains(null))
{
distinctValues.remove(null);
for (int i = 0; i < valueList.size(); i++)
{
if (valueList.get(i) == null)
{
valueList.remove(i);
iNullValueCount++;
i--;
continue;
}
}
}
// Sort the values of the passed Map
if (ascendingOrder == null)
{
// If Boolean ascendingOrder is null, use passed comparator for order of sorting values
Collections.sort(valueList, comparator);
}
else if (ascendingOrder)
{
// If Boolean ascendingOrder is not null and is true, sort values in ascending order
Collections.sort(valueList);
}
else
{
// If Boolean ascendingOrder is not null and is false, sort values in descending order
Collections.sort(valueList);
Collections.reverse(valueList);
}
// Check if there are multiple same values exist in passed Map (not considering null values)
boolean bAllDistinct = true;
if (iSize != (distinctValues.size() + iNullValueCount))
bAllDistinct = false;
Object key = null, value = null, sortedValue;
Set keySet = null;
Iterator itKeyList = null;
HashMap hmTmpMap = new HashMap(iSize);
HashMap hmNullValueMap = new HashMap();
if (bAllDistinct)
{
// There are no multiple same values in the passed map (without consedring null)
keySet = inMap.keySet();
itKeyList = keySet.iterator();
while (itKeyList.hasNext())
{
key = itKeyList.next();
value = inMap.get(key);
if (value != null)
hmTmpMap.put(value, key); // Prepare new temp HashMap with value=key combination
else
hmNullValueMap.put(key, value); // Keep all null values in a new temp Map
}
if (ascendingOrder != null && !ascendingOrder)
{
// As it is descending order, Add Null Values in first place of the LinkedHasMap
sortedMap.putAll(hmNullValueMap);
}
// Put all not null values in returning LinkedHashMap
for (int i = 0; i < valueList.size(); i++)
{
value = valueList.get(i);
key = hmTmpMap.get(value);
sortedMap.put(key, value);
}
if (ascendingOrder == null || ascendingOrder)
{
// Add Null Values in the last of the LinkedHasMap
sortedMap.putAll(hmNullValueMap);
}
}
else
{
// There are some multiple values (with out considering null)
keySet = inMap.keySet();
itKeyList = keySet.iterator();
while (itKeyList.hasNext())
{
key = itKeyList.next();
value = inMap.get(key);
if (value != null)
hmTmpMap.put(key, value); // Prepare new temp HashMap with key=value combination
else
hmNullValueMap.put(key, value); // Keep all null values in a new temp Map
}
if (ascendingOrder != null && !ascendingOrder)
{
// As it is descending order, Add Null Values in first place of the LinkedHasMap
sortedMap.putAll(hmNullValueMap);
}
// Put all not null values in returning LinkedHashMap
for (int i = 0; i < valueList.size(); i++)
{
sortedValue = valueList.get(i);
// Search this value in temp HashMap and if found remove it
keySet = hmTmpMap.keySet();
itKeyList = keySet.iterator();
while (itKeyList.hasNext())
{
key = itKeyList.next();
value = hmTmpMap.get(key);
if (value.equals(sortedValue))
{
sortedMap.put(key, value);
hmTmpMap.remove(key);
break;
}
}
}
if (ascendingOrder == null || ascendingOrder)
{
// Add Null Values in the last of the LinkedHasMap
sortedMap.putAll(hmNullValueMap);
}
}
return sortedMap;
}
}