先对整数列表排序,然后在 java 8 中按被 10 整除排序
Sort the integer list first and then sort by divisible by 10 in java 8
我有包含 {3,10,17,9,20,15,40,30, 55} 的数组列表,所以我想对这个方法进行排序,以便所有可被 10 整除的值排在排序列表的最后在排序列表之后。
即 o/p 应该是这样的:{3, 9, 15, 17, 55, 10, 20, 30, 40}
我已尝试使用以下代码,但无法成功整理出此列表,
List<Integer> list = Arrays.asList(3,10,17,9,20,55,40,30);
list.stream().sorted(((Comparator<Integer>) (v1, v2) -> Integer.compare(v1, v2))).sorted((Comparator<Integer>) (v1, v2) -> v1 % 10 == 0 ? 0 : -1).forEach(System.out::println);
以上代码的输出是:
55
17
9
3个
10
20
30
40
谢谢,
您似乎想从逻辑上将数字分成两组,然后分别对每组进行排序。
您可以根据除以 10 的标准拆分列表,然后分别对 2 个子列表进行排序,或者您可以使用单个 Comparator
检查是否2个比较数字属于同一组:
- 如果他们不这样做,则根据组确定哪个应该排在第一位
如果他们这样做,请按他们的价值在他们的组内比较他们
list.stream()
.sorted((v1, v2) -> {
if (v1 % 10 == 0) {
if (v2 % 10 == 0)
return Integer.compare(v1, v2); // both are divisible by 10
// sort by value
else
return 1; // only v1 is divisible by 10, should come after v2
} else {
if (v2 % 10 != 0)
return Integer.compare(v1, v2); // both are not divisible by 10
// sort by value
else
return -1; // only v2 is divisible by 10, should come after v1
}
})
.forEach(System.out::println);
输出:
3
9
17
55
10
20
30
40
要实现这一点,您需要:
- 首先把列表分成两个列表,一个是数字能被整除的列表
10
第二个是那些不是的人。
- 那就单独排序吧
- 最后将第一个附加到第二个。
你的代码应该是这样的:
List<Integer> dividedBy10 = list.stream()
.filter(p -> p % 10 == 0).collect(Collectors.toList());
Collections.sort(dividedBy10);
List<Integer> others = list.stream()
.filter(p -> p % 10 != 0).collect(Collectors.toList());
Collections.sort(others);
//Then append the first list to the sorted one
others.addAll(dividedBy10);
编辑:
或者像 @yahya 建议的那样,您可以只对原始列表进行排序,然后将其过滤成列表并稍后附加这两个列表:
Collections.sort(list);
List<Integer> dividedBy10 = list.stream()
.filter(p -> p % 10 == 0).collect(Collectors.toList());
List<Integer> others = list.stream()
.filter(p -> p % 10 != 0).collect(Collectors.toList());
others.addAll(dividedBy10);
需要单次排序:
list.stream().sorted(((Comparator<Integer>) (v1, v2) -> {
// if both are divisible by 10, you sort them with their order natural
if (v1 % 10 == 0 && v2 % 10 == 0) {
return Integer.compare(v1, v2);
}
// if only the first argument is divisible by 10, it is always at the end
else if (v1 % 10 == 0) {
return 1;
}
// if only the second argument is divisible by 10, it is always at the end
else if (v2 % 10 == 0) {
return -1;
}
// in other cases, you sort by natural order
return Integer.compare(v1, v2);
}))
.forEach(System.out::println);
这是输出:
3 9 17 55 10 20 30 40
目前,您正在对不能被 10 整除的数字取反,作为一种黑客手段,以便首先将它们取出。但这会颠倒这些数字的顺序,这会影响您的输出!
比较被 10 整除的数字时需要更加小心,因此比较器将它们排在其他数字的后面。这样的事情会起作用:
list.stream().sorted(((Comparator<Integer>) (v1, v2) -> {
if (v1 % 10 == 0 && v2 % 10 == 0) {
return Integer.compare(v1, v2);
} else if (v1 % 10 == 0) {
// v2 is effectively larger
return -1;
} else if (v2 % 10 == 0) {
// v1 is effectively larger
return 1;
}
return Integer.compare(v1, v2);
}))/*etc*/
(a,b) -> (a<b?-1:a==b?0:1) + (a%10==0?2:0) - (b%10==0?2:0)
这是如何工作的:
(a<b?-1:a==b?0:1)
通常比较整数(权重为 1)
+ (a%10==0?2:0)
检查第一个整数是否能被 10 整除(权重为 2)
- (b%10==0?2:0)
检查第二个整数是否能被 10 整除(权重为 2)
只要 Integer.compare
只有 returns -1,0,1 你就可以使用这个(但是 @Holger 指出没有保证)
(a,b) -> Integer.compare(a, b) + (a%10==0?2:0) - (b%10==0?2:0)
您只有三个 return 值:
Integer.compare(a, b)
如果两个值都可以被 10 整除,当它们不能被 10 整除时
> 0
如果第一个值能被 10 整除
< 0
否则
list.sort((a, b) -> {
if ((a % 10 == 0) == (b % 10 == 0)) {
return a.compareTo(b);
} else {
return a % 10 == 0 ? 1 : -1;
}
});
或者如果您更喜欢不可读的代码
list.sort((a, b) -> (a % 10 == 0) == (b % 10 == 0) ? a.compareTo(b) : a % 10 == 0 ? 1 : -1);
有两件事要知道。
首先,当您知道 Boolean
值自 Java 5 以来具有可比性时,排序时按特定谓词分组非常容易。因此您可以使用
Comparator.comparing(i -> i%10==0)
对可被 10 整除的数字排序到最后。
其次,您可以使用 thenComparing
链接比较器,这样根据第一个比较器相等的元素将根据下一个比较器排序。
一起运算就变成了
List<Integer> list = Arrays.asList(3,10,17,9,20,55,40,30);
list.stream()
.sorted(Comparator.comparing((Integer i) -> i%10==0)
.thenComparing(Comparator.naturalOrder()))
.forEach(System.out::println);
请注意,由于类型推断的限制,完整操作需要第一个 lambda 表达式 ((Integer i)
) 的显式类型参数。
你也可以这样写
list.stream()
.sorted(Comparator.comparing((Integer i) -> i%10==0)
.thenComparingInt(i -> i))
.forEach(System.out::println);
不过,我更喜欢在适用时重用现有的比较器 Comparator.naturalOrder()
。
我有包含 {3,10,17,9,20,15,40,30, 55} 的数组列表,所以我想对这个方法进行排序,以便所有可被 10 整除的值排在排序列表的最后在排序列表之后。 即 o/p 应该是这样的:{3, 9, 15, 17, 55, 10, 20, 30, 40}
我已尝试使用以下代码,但无法成功整理出此列表,
List<Integer> list = Arrays.asList(3,10,17,9,20,55,40,30);
list.stream().sorted(((Comparator<Integer>) (v1, v2) -> Integer.compare(v1, v2))).sorted((Comparator<Integer>) (v1, v2) -> v1 % 10 == 0 ? 0 : -1).forEach(System.out::println);
以上代码的输出是: 55 17 9 3个 10 20 30 40
谢谢,
您似乎想从逻辑上将数字分成两组,然后分别对每组进行排序。
您可以根据除以 10 的标准拆分列表,然后分别对 2 个子列表进行排序,或者您可以使用单个 Comparator
检查是否2个比较数字属于同一组:
- 如果他们不这样做,则根据组确定哪个应该排在第一位
如果他们这样做,请按他们的价值在他们的组内比较他们
list.stream() .sorted((v1, v2) -> { if (v1 % 10 == 0) { if (v2 % 10 == 0) return Integer.compare(v1, v2); // both are divisible by 10 // sort by value else return 1; // only v1 is divisible by 10, should come after v2 } else { if (v2 % 10 != 0) return Integer.compare(v1, v2); // both are not divisible by 10 // sort by value else return -1; // only v2 is divisible by 10, should come after v1 } }) .forEach(System.out::println);
输出:
3
9
17
55
10
20
30
40
要实现这一点,您需要:
- 首先把列表分成两个列表,一个是数字能被整除的列表
10
第二个是那些不是的人。 - 那就单独排序吧
- 最后将第一个附加到第二个。
你的代码应该是这样的:
List<Integer> dividedBy10 = list.stream()
.filter(p -> p % 10 == 0).collect(Collectors.toList());
Collections.sort(dividedBy10);
List<Integer> others = list.stream()
.filter(p -> p % 10 != 0).collect(Collectors.toList());
Collections.sort(others);
//Then append the first list to the sorted one
others.addAll(dividedBy10);
编辑:
或者像 @yahya 建议的那样,您可以只对原始列表进行排序,然后将其过滤成列表并稍后附加这两个列表:
Collections.sort(list);
List<Integer> dividedBy10 = list.stream()
.filter(p -> p % 10 == 0).collect(Collectors.toList());
List<Integer> others = list.stream()
.filter(p -> p % 10 != 0).collect(Collectors.toList());
others.addAll(dividedBy10);
需要单次排序:
list.stream().sorted(((Comparator<Integer>) (v1, v2) -> {
// if both are divisible by 10, you sort them with their order natural
if (v1 % 10 == 0 && v2 % 10 == 0) {
return Integer.compare(v1, v2);
}
// if only the first argument is divisible by 10, it is always at the end
else if (v1 % 10 == 0) {
return 1;
}
// if only the second argument is divisible by 10, it is always at the end
else if (v2 % 10 == 0) {
return -1;
}
// in other cases, you sort by natural order
return Integer.compare(v1, v2);
}))
.forEach(System.out::println);
这是输出:
3 9 17 55 10 20 30 40
目前,您正在对不能被 10 整除的数字取反,作为一种黑客手段,以便首先将它们取出。但这会颠倒这些数字的顺序,这会影响您的输出!
比较被 10 整除的数字时需要更加小心,因此比较器将它们排在其他数字的后面。这样的事情会起作用:
list.stream().sorted(((Comparator<Integer>) (v1, v2) -> {
if (v1 % 10 == 0 && v2 % 10 == 0) {
return Integer.compare(v1, v2);
} else if (v1 % 10 == 0) {
// v2 is effectively larger
return -1;
} else if (v2 % 10 == 0) {
// v1 is effectively larger
return 1;
}
return Integer.compare(v1, v2);
}))/*etc*/
(a,b) -> (a<b?-1:a==b?0:1) + (a%10==0?2:0) - (b%10==0?2:0)
这是如何工作的:
(a<b?-1:a==b?0:1)
通常比较整数(权重为 1)
+ (a%10==0?2:0)
检查第一个整数是否能被 10 整除(权重为 2)
- (b%10==0?2:0)
检查第二个整数是否能被 10 整除(权重为 2)
只要 Integer.compare
只有 returns -1,0,1 你就可以使用这个(但是 @Holger 指出没有保证)
(a,b) -> Integer.compare(a, b) + (a%10==0?2:0) - (b%10==0?2:0)
您只有三个 return 值:
Integer.compare(a, b)
如果两个值都可以被 10 整除,当它们不能被 10 整除时> 0
如果第一个值能被 10 整除< 0
否则
list.sort((a, b) -> {
if ((a % 10 == 0) == (b % 10 == 0)) {
return a.compareTo(b);
} else {
return a % 10 == 0 ? 1 : -1;
}
});
或者如果您更喜欢不可读的代码
list.sort((a, b) -> (a % 10 == 0) == (b % 10 == 0) ? a.compareTo(b) : a % 10 == 0 ? 1 : -1);
有两件事要知道。
首先,当您知道 Boolean
值自 Java 5 以来具有可比性时,排序时按特定谓词分组非常容易。因此您可以使用
Comparator.comparing(i -> i%10==0)
对可被 10 整除的数字排序到最后。
其次,您可以使用 thenComparing
链接比较器,这样根据第一个比较器相等的元素将根据下一个比较器排序。
一起运算就变成了
List<Integer> list = Arrays.asList(3,10,17,9,20,55,40,30);
list.stream()
.sorted(Comparator.comparing((Integer i) -> i%10==0)
.thenComparing(Comparator.naturalOrder()))
.forEach(System.out::println);
请注意,由于类型推断的限制,完整操作需要第一个 lambda 表达式 ((Integer i)
) 的显式类型参数。
你也可以这样写
list.stream()
.sorted(Comparator.comparing((Integer i) -> i%10==0)
.thenComparingInt(i -> i))
.forEach(System.out::println);
不过,我更喜欢在适用时重用现有的比较器 Comparator.naturalOrder()
。