这里我的rowId就像下面的
1
1.1
1.2
1.9
2
2.1
。 3 。 。 9
9.9
10
10.1
List<MyBean> sortedList = rootItems.stream().sorted(Comparator.comparing(MyBean::getRowId)) .collect(Collectors.toList());
通过使用上面的代码,我得到如下的输出。
1
10
11
12
2
2.1
2.2
但我想要输出如下
1
1.1
1.1.1
1.1.1.1
1.2
1.3
1.9
10
11
2
2.1
2.2
2.3
3
3.1
3.2
4
9
9.1
9.2
9.9
10
10.1
。
。
像这样需要继续
如果我想要这样哪个Set我需要使用
答案 0 :(得分:0)
我没有在我的计算机上尝试过,但似乎数据没有翻译成双倍的比较。我认为在排序之前添加mapToDouble(i->i.getRowId)
可以解决您的问题。
答案 1 :(得分:0)
使用自己的compare()
方法,如下所示:
Collections.sort(myList, new Comparator<String>() {
@Override
public int compare(String id1, String id2) {
double d1 = Double.parseDouble(id1);
double d2 = Double.parseDouble(id2);
return Double.compare(d1, d2);
}
});
或者只是解析/ map将ID转换为double并对其进行比较/排序。
答案 2 :(得分:0)
正如我在评论中所述,问题是字符串是逐个字符进行比较的。因此,您需要更改字符串,以便每个元素具有相等的长度,并且每个字符位置对应于其他ID中的相同位置,或者将元素解析为数字序列
备选方案1的缺点是,您需要为每个组件设置固定的最大长度(即a.b.c
中的a,b,c等),或者您必须计算元素的数量第一
备选方案2因此似乎更好,但每次比较它们时解析字符串可能会有点代价。因此,您可能希望引入一个表示您的id的类,该类包含实际的id字符串以及解析的版本。该类可以实现Comparable
并仅对解析后的版本进行操作。
示例:
class MyRowId implements Comparable<MyRowId> {
private final String id;
//when serializing instances of that class you might want to ignore this array
//and upon deserialization parse the string again
private final int[] parsed;
public MyRowId( String idString ) {
id = idString;
parsed = Arrays.stream( idString.split("\\.") ).mapToInt( Integer::parseInt ).toArray();
}
public int compareTo( MyRowId other ) {
//Compare the elements one by one until we run out of elements or hit a difference
//There might be a more Java8-ish way but I didn't find it yet
for( int i = 0; i < Math.min( parsed.length, other.parsed.length ); i++ ) {
int r = Integer.compare( parsed[i], other.parsed[i] );
if( r != 0 ) {
return r;
}
}
//If we're here all compared elements were equal but one id might be longer so compare the lengths.
//That would handle things like comparing "1.1" to "1.1.1" where the latter is greater.
return Integer.compare( parsed.length, other.parsed.length );
}
}
答案 3 :(得分:0)
如果您在内部将它们标准化,那么比较这些字符串会更容易,然后可以对其进行排序。我建议用零填充单个项目,如下所示:
private static final Pattern SINGLE_DIGIT = Pattern.compile("\\b(\\d)\\b");
...
String padWithZeroes = SINGLE_DIGIT.matcher(yourInputString).replaceAll("0$1");
现在只需对填充的字符串进行排序。 假设最高数字是2位数,如果不是,我们需要调整正则表达式,逻辑会稍微复杂一点。
如果任何数字段可能超过2位数,那么它将变得更复杂。这是一种将所有段填充到最大长度的方法:
static String padWithZeroes(String yourInputString, int digits) {
final Matcher matcher = SINGLE_DIGIT.matcher(yourInputString);
StringBuffer sb = new StringBuffer();
while(matcher.find()){
matcher.appendReplacement(sb, pad(digits - matcher.group().length())+matcher.group());
}
matcher.appendTail(sb);
return sb.toString();
}
static String pad(int length) {
final char[] chars = new char[length];
Arrays.fill(chars, '0');
return new String(chars);
}
这里的问题是你必须预先知道digits
参数的值,所以要么你知道你的数据,要么你必须做一个单独的迭代来测量最大长度。
答案 4 :(得分:-2)
如果您指定了getRowId()的返回类型,那么实现可能会有所不同。
您可能需要为MyBean类定义Comparator。它可以实现为
在你的情况下,它可能是:
class MyBeanComparator implements Comparator<MyBean>{
public static final MyBeanComparator INSTANCE = new MyBeanComparator();
public int compare(MyBean b1, MyBean b2){
//your custom rules
}
}
然后
List<MyBean> sortedList = rootItems.stream().sorted(MyBeanComparator.INSTANCE::compare) .collect(Collectors.toList());