按字母顺序对 TreeMap 进行排序
Sorting TreeMap alphabetically
我有一个 typer person 的对象,它有一个名称作为属性。
我有一个树状图,其中 link 人到远处,这是一个整数。
我需要按字母顺序对 TreeMap 进行排序,方法是查看其中每个人的姓名。
我该怎么做?
谢谢你的回答。
Eric Berry 写了一个方便的 class,它通过人类值而不是传统的机器值来比较字符串。下面是它的修改版本以及对象比较器(我认为你正在寻找的)及其测试 class.
关于如何使用字符串比较器的示例:
Map<String,String> humanSortedMap = new TreeMap<>(new AlphaNumericStringComparator());
关于如何使用对象比较器的示例,但这次使用的是 List 而不是 TreeMap:
Collections.sort(humanSortedList, new AlphaNumericObjectComparator<QuartzJobWrapper>()
{
@Override
public int compare(QuartzJobWrapper t1, QuartzJobWrapper t2)
{
return compareStrings(t1.getName(), t2.getName());
}
});
AlphaNumericStringComparator 来源:
/*
* Copyright (c) 2007 Eric Berry <elberry@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import java.text.DecimalFormatSymbols;
import java.util.Comparator;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
/**
* Compares Strings by human values instead of traditional machine values.
*
* @author elberry
* @modified Tristan Everitt
*/
public class AlphaNumericStringComparator implements Comparator<String>
{
private Pattern alphaNumChunkPattern;
public AlphaNumericStringComparator()
{
this(Locale.getDefault());
}
public AlphaNumericStringComparator(Locale locale)
{
DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
char localeDecimalSeparator = dfs.getDecimalSeparator();
// alphaNumChunkPatter initialized here to get correct decimal separator for locale.
alphaNumChunkPattern = Pattern.compile("(\d+\" + localeDecimalSeparator + "\d+)|(\d+)|(\D+)");
}
@Override
public int compare(String s1, String s2)
{
int compareValue = 0;
Matcher s1ChunkMatcher = alphaNumChunkPattern.matcher(s1);
Matcher s2ChunkMatcher = alphaNumChunkPattern.matcher(s2);
String s1ChunkValue = null;
String s2ChunkValue = null;
while (s1ChunkMatcher.find() && s2ChunkMatcher.find() && compareValue == 0)
{
s1ChunkValue = s1ChunkMatcher.group();
s2ChunkValue = s2ChunkMatcher.group();
// teveritt - Remove white space and make lower case to neutralise it
s1ChunkValue = s1ChunkValue.replaceAll("\s+", "");
s2ChunkValue = s2ChunkValue.replaceAll("\s+", "");
s1ChunkValue = StringUtils.lowerCase(s1ChunkValue);
s2ChunkValue = StringUtils.lowerCase(s2ChunkValue);
try
{
// compare double values - ints get converted to doubles. Eg. 100 = 100.0
Double s1Double = Double.valueOf(s1ChunkValue);
Double s2Double = Double.valueOf(s2ChunkValue);
compareValue = s1Double.compareTo(s2Double);
}
catch (NumberFormatException e)
{
// not a number, use string comparison.
compareValue = s1ChunkValue.compareTo(s2ChunkValue);
}
// if they are equal thus far, but one has more left, it should come after the one that doesn't.
if (compareValue == 0)
{
if (s1ChunkMatcher.hitEnd() && !s2ChunkMatcher.hitEnd())
{
compareValue = -1;
}
else if (!s1ChunkMatcher.hitEnd() && s2ChunkMatcher.hitEnd())
{
compareValue = 1;
}
}
}
return compareValue;
}
}
AlphaNumericObjectComparator 来源:
/**
* Compares Objects by human values instead of traditional machine values.
*
* @modified Tristan Everitt
*/
public class AlphaNumericObjectComparator<T> implements Comparator<T>
{
private AlphaNumericStringComparator stringComparator;
public AlphaNumericObjectComparator()
{
this(Locale.getDefault());
}
public AlphaNumericObjectComparator(Locale locale)
{
this.stringComparator = new AlphaNumericStringComparator(locale);
}
@Override
public int compare(T t1, T t2)
{
return compareStrings(t1.toString(), t2.toString());
}
protected int compareStrings(String s1, String s2)
{
return stringComparator.compare(s1, s2);
}
}
AlphaNumericStringComparatorTester 来源:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.junit.Test;
/**
*
* @author Tristan Everitt
*/
public class AlphaNumericStringComparatorTester
{
@Test
public void testHumanNaturalSort1()
{
List<String> randomList = Arrays.asList("z1.doc", "z10.doc", "z100.doc", "z101.doc", "z102.doc", "z11.doc", "z12.doc", "z13.doc", "z14.doc", "z15.doc", "z16.doc", "z17.doc", "z18.doc",
"z19.doc", "z2.doc", "z20.doc", "z3.doc", "z4.doc", "z5.doc", "z6.doc", "z7.doc", "z8.doc", "z9.doc", "z1.2.doc", "z1.3.doc");
Collections.shuffle(randomList, new Random());
List<String> expected = Arrays.asList("z1.doc", "z1.2.doc", "z1.3.doc", "z2.doc", "z3.doc", "z4.doc", "z5.doc", "z6.doc", "z7.doc", "z8.doc", "z9.doc", "z10.doc", "z11.doc", "z12.doc",
"z13.doc", "z14.doc", "z15.doc", "z16.doc", "z17.doc", "z18.doc", "z19.doc", "z20.doc", "z100.doc", "z101.doc", "z102.doc");
assertNotEquals(expected, randomList);
Collections.sort(randomList, new AlphaNumericStringComparator());
assertEquals(expected, randomList);
}
@Test
public void testHumanNaturalSort2()
{
List<String> randomList = Arrays.asList("z1.doc", "z10.doc", "z100.doc", "z101.doc", "z102.doc", "z11.doc", "z12.doc", "z13.doc", "z14.doc", "z15.doc", "z16.doc", "z17.doc", "z18.doc",
"z19.doc", "z2.doc", "z20.doc", "z3.doc", "z4.doc", "z5.doc", "z6.doc", "z7.doc", "z8.doc", "z9.doc", "z1.2.doc", "z1.3.doc");
Collections.shuffle(randomList, new Random());
List<String> expected = Arrays.asList("z1.doc", "z1.2.doc", "z1.3.doc", "z2.doc", "z3.doc", "z4.doc", "z5.doc", "z6.doc", "z7.doc", "z8.doc", "z9.doc", "z10.doc", "z11.doc", "z12.doc",
"z13.doc", "z14.doc", "z15.doc", "z16.doc", "z17.doc", "z18.doc", "z19.doc", "z20.doc", "z100.doc", "z101.doc", "z102.doc");
assertNotEquals(expected, randomList);
Collections.sort(randomList, new AlphaNumericStringComparator());
assertEquals(expected, randomList);
}
@Test
public void testHumanNaturalSort3()
{
List<String> randomList = Arrays.asList("yr1", "yr10", "yr11", "yr12", "yr13", "yr2", "yr 3", "yr 3.4", "yr 4", "yr5", "yr6", "yr7", "yr8", "yr 9");
Collections.shuffle(randomList, new Random());
List<String> expected = Arrays.asList("yr1", "yr2", "yr 3", "yr 3.4", "yr 4", "yr5", "yr6", "yr7", "yr8", "yr 9", "yr10", "yr11", "yr12", "yr13");
assertNotEquals(expected, randomList);
Collections.sort(randomList, new AlphaNumericStringComparator());
assertEquals(expected, randomList);
}
@Test
public void testHumanNaturalSort4()
{
List<String> randomList = Arrays.asList("1-2", "1-02", "1-20", "10-20", "fred", "jane", "pic01", "pic2", "pic02", "pic02a", "pic3", "pic4", "pic 4 else", "pic 5", "pic05", "pic 5",
"pic 5 something", "pic 6", "pic 7", "pic100", "pic100a", "pic120", "pic121", "pic02000", "tom", "x2-g8", "x2-y7", "x2-y08", "x8-y8");
Collections.shuffle(randomList, new Random());
List<String> expected = Arrays.asList("1-2", "1-02", "1-20", "10-20", "fred", "jane", "pic01", "pic02", "pic2", "pic02a", "pic3", "pic4", "pic 4 else", "pic 5", "pic05", "pic 5",
"pic 5 something", "pic 6", "pic 7", "pic100", "pic100a", "pic120", "pic121", "pic02000", "tom", "x2-g8", "x2-y7", "x2-y08", "x8-y8");
assertNotEquals(expected, randomList);
Collections.sort(randomList, new AlphaNumericStringComparator());
assertEquals(expected, randomList);
}
}
我有一个 typer person 的对象,它有一个名称作为属性。 我有一个树状图,其中 link 人到远处,这是一个整数。
我需要按字母顺序对 TreeMap 进行排序,方法是查看其中每个人的姓名。
我该怎么做? 谢谢你的回答。
Eric Berry 写了一个方便的 class,它通过人类值而不是传统的机器值来比较字符串。下面是它的修改版本以及对象比较器(我认为你正在寻找的)及其测试 class.
关于如何使用字符串比较器的示例:
Map<String,String> humanSortedMap = new TreeMap<>(new AlphaNumericStringComparator());
关于如何使用对象比较器的示例,但这次使用的是 List 而不是 TreeMap:
Collections.sort(humanSortedList, new AlphaNumericObjectComparator<QuartzJobWrapper>()
{
@Override
public int compare(QuartzJobWrapper t1, QuartzJobWrapper t2)
{
return compareStrings(t1.getName(), t2.getName());
}
});
AlphaNumericStringComparator 来源:
/*
* Copyright (c) 2007 Eric Berry <elberry@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import java.text.DecimalFormatSymbols;
import java.util.Comparator;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
/**
* Compares Strings by human values instead of traditional machine values.
*
* @author elberry
* @modified Tristan Everitt
*/
public class AlphaNumericStringComparator implements Comparator<String>
{
private Pattern alphaNumChunkPattern;
public AlphaNumericStringComparator()
{
this(Locale.getDefault());
}
public AlphaNumericStringComparator(Locale locale)
{
DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
char localeDecimalSeparator = dfs.getDecimalSeparator();
// alphaNumChunkPatter initialized here to get correct decimal separator for locale.
alphaNumChunkPattern = Pattern.compile("(\d+\" + localeDecimalSeparator + "\d+)|(\d+)|(\D+)");
}
@Override
public int compare(String s1, String s2)
{
int compareValue = 0;
Matcher s1ChunkMatcher = alphaNumChunkPattern.matcher(s1);
Matcher s2ChunkMatcher = alphaNumChunkPattern.matcher(s2);
String s1ChunkValue = null;
String s2ChunkValue = null;
while (s1ChunkMatcher.find() && s2ChunkMatcher.find() && compareValue == 0)
{
s1ChunkValue = s1ChunkMatcher.group();
s2ChunkValue = s2ChunkMatcher.group();
// teveritt - Remove white space and make lower case to neutralise it
s1ChunkValue = s1ChunkValue.replaceAll("\s+", "");
s2ChunkValue = s2ChunkValue.replaceAll("\s+", "");
s1ChunkValue = StringUtils.lowerCase(s1ChunkValue);
s2ChunkValue = StringUtils.lowerCase(s2ChunkValue);
try
{
// compare double values - ints get converted to doubles. Eg. 100 = 100.0
Double s1Double = Double.valueOf(s1ChunkValue);
Double s2Double = Double.valueOf(s2ChunkValue);
compareValue = s1Double.compareTo(s2Double);
}
catch (NumberFormatException e)
{
// not a number, use string comparison.
compareValue = s1ChunkValue.compareTo(s2ChunkValue);
}
// if they are equal thus far, but one has more left, it should come after the one that doesn't.
if (compareValue == 0)
{
if (s1ChunkMatcher.hitEnd() && !s2ChunkMatcher.hitEnd())
{
compareValue = -1;
}
else if (!s1ChunkMatcher.hitEnd() && s2ChunkMatcher.hitEnd())
{
compareValue = 1;
}
}
}
return compareValue;
}
}
AlphaNumericObjectComparator 来源:
/**
* Compares Objects by human values instead of traditional machine values.
*
* @modified Tristan Everitt
*/
public class AlphaNumericObjectComparator<T> implements Comparator<T>
{
private AlphaNumericStringComparator stringComparator;
public AlphaNumericObjectComparator()
{
this(Locale.getDefault());
}
public AlphaNumericObjectComparator(Locale locale)
{
this.stringComparator = new AlphaNumericStringComparator(locale);
}
@Override
public int compare(T t1, T t2)
{
return compareStrings(t1.toString(), t2.toString());
}
protected int compareStrings(String s1, String s2)
{
return stringComparator.compare(s1, s2);
}
}
AlphaNumericStringComparatorTester 来源:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.junit.Test;
/**
*
* @author Tristan Everitt
*/
public class AlphaNumericStringComparatorTester
{
@Test
public void testHumanNaturalSort1()
{
List<String> randomList = Arrays.asList("z1.doc", "z10.doc", "z100.doc", "z101.doc", "z102.doc", "z11.doc", "z12.doc", "z13.doc", "z14.doc", "z15.doc", "z16.doc", "z17.doc", "z18.doc",
"z19.doc", "z2.doc", "z20.doc", "z3.doc", "z4.doc", "z5.doc", "z6.doc", "z7.doc", "z8.doc", "z9.doc", "z1.2.doc", "z1.3.doc");
Collections.shuffle(randomList, new Random());
List<String> expected = Arrays.asList("z1.doc", "z1.2.doc", "z1.3.doc", "z2.doc", "z3.doc", "z4.doc", "z5.doc", "z6.doc", "z7.doc", "z8.doc", "z9.doc", "z10.doc", "z11.doc", "z12.doc",
"z13.doc", "z14.doc", "z15.doc", "z16.doc", "z17.doc", "z18.doc", "z19.doc", "z20.doc", "z100.doc", "z101.doc", "z102.doc");
assertNotEquals(expected, randomList);
Collections.sort(randomList, new AlphaNumericStringComparator());
assertEquals(expected, randomList);
}
@Test
public void testHumanNaturalSort2()
{
List<String> randomList = Arrays.asList("z1.doc", "z10.doc", "z100.doc", "z101.doc", "z102.doc", "z11.doc", "z12.doc", "z13.doc", "z14.doc", "z15.doc", "z16.doc", "z17.doc", "z18.doc",
"z19.doc", "z2.doc", "z20.doc", "z3.doc", "z4.doc", "z5.doc", "z6.doc", "z7.doc", "z8.doc", "z9.doc", "z1.2.doc", "z1.3.doc");
Collections.shuffle(randomList, new Random());
List<String> expected = Arrays.asList("z1.doc", "z1.2.doc", "z1.3.doc", "z2.doc", "z3.doc", "z4.doc", "z5.doc", "z6.doc", "z7.doc", "z8.doc", "z9.doc", "z10.doc", "z11.doc", "z12.doc",
"z13.doc", "z14.doc", "z15.doc", "z16.doc", "z17.doc", "z18.doc", "z19.doc", "z20.doc", "z100.doc", "z101.doc", "z102.doc");
assertNotEquals(expected, randomList);
Collections.sort(randomList, new AlphaNumericStringComparator());
assertEquals(expected, randomList);
}
@Test
public void testHumanNaturalSort3()
{
List<String> randomList = Arrays.asList("yr1", "yr10", "yr11", "yr12", "yr13", "yr2", "yr 3", "yr 3.4", "yr 4", "yr5", "yr6", "yr7", "yr8", "yr 9");
Collections.shuffle(randomList, new Random());
List<String> expected = Arrays.asList("yr1", "yr2", "yr 3", "yr 3.4", "yr 4", "yr5", "yr6", "yr7", "yr8", "yr 9", "yr10", "yr11", "yr12", "yr13");
assertNotEquals(expected, randomList);
Collections.sort(randomList, new AlphaNumericStringComparator());
assertEquals(expected, randomList);
}
@Test
public void testHumanNaturalSort4()
{
List<String> randomList = Arrays.asList("1-2", "1-02", "1-20", "10-20", "fred", "jane", "pic01", "pic2", "pic02", "pic02a", "pic3", "pic4", "pic 4 else", "pic 5", "pic05", "pic 5",
"pic 5 something", "pic 6", "pic 7", "pic100", "pic100a", "pic120", "pic121", "pic02000", "tom", "x2-g8", "x2-y7", "x2-y08", "x8-y8");
Collections.shuffle(randomList, new Random());
List<String> expected = Arrays.asList("1-2", "1-02", "1-20", "10-20", "fred", "jane", "pic01", "pic02", "pic2", "pic02a", "pic3", "pic4", "pic 4 else", "pic 5", "pic05", "pic 5",
"pic 5 something", "pic 6", "pic 7", "pic100", "pic100a", "pic120", "pic121", "pic02000", "tom", "x2-g8", "x2-y7", "x2-y08", "x8-y8");
assertNotEquals(expected, randomList);
Collections.sort(randomList, new AlphaNumericStringComparator());
assertEquals(expected, randomList);
}
}