首先对整数列表进行排序,然后在java 8中按10整除排序

时间:2017-07-24 10:09:46

标签: java list sorting collections comparator

我有包含{3,10,17,9,20,15,40,30,55}的arraylist所以我想对这个方法进行排序,以便所有可被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 三十 40

谢谢,

7 个答案:

答案 0 :(得分:3)

看起来您希望将数字逻辑划分为两组,并分别对每个组进行排序。

您可以根据划分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

答案 1 :(得分:3)

有两件事要知道。

首先,当您知道自Java 5以来Boolean值具有可比性时,在排序时很容易按特定谓词进行分组。所以您可以使用

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()

答案 2 :(得分:1)

要实现这一目标,您需要:

  • 首先将列表分成两个列表,一个列表可以被整除 10,第二个与不是。{/ li>
  • 然后单独对它们进行排序
  • 最后将第一个追加到第二个。

这应该是你的代码:

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);

答案 3 :(得分:1)

目前,你正在否定那些不能被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*/

答案 4 :(得分:0)

需要单一种类:

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

答案 5 :(得分:0)

(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只返回-1,0,1就可以使用它(但是@Holger指出没有保证)

(a,b) -> Integer.compare(a, b) + (a%10==0?2:0) - (b%10==0?2:0)

答案 6 :(得分:0)

您只有三个返回值:

  • Integer.compare(a, b)如果两个值都可以被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);