Làm cách nào để sử dụng lambda Java8 để sắp xếp luồng theo thứ tự ngược lại?


181

Tôi đang sử dụng java lambda để sắp xếp một danh sách.

Làm thế nào tôi có thể sắp xếp nó theo một cách ngược lại?

Tôi đã thấy bài đăng này , nhưng tôi muốn sử dụng java 8 lambda.

Đây là mã của tôi (tôi đã sử dụng * -1) như một bản hack

Arrays.asList(files).stream()
    .filter(file -> isNameLikeBaseLine(file, baseLineFile.getName()))
    .sorted(new Comparator<File>() {
        public int compare(File o1, File o2) {
            int answer;
            if (o1.lastModified() == o2.lastModified()) {
                answer = 0;
            } else if (o1.lastModified() > o2.lastModified()) {
                answer = 1;
            } else {
                answer = -1;
            }
            return -1 * answer;
        }
    })
    .skip(numOfNewestToLeave)
    .forEach(item -> item.delete());

Bạn có ý nghĩa gì bởi "trật tự ngược"? Nếu bạn thay thế -1 * answerbằng answer, thứ tự sẽ thay đổi để đảo ngược với những gì nó đã được với -1 * ....
dasblinkenlight 19/2/2015

2
Coi chừng! Tất cả các mã của bạn cho thấy rằng bạn muốn sử dụng forEachOrderedthay vìforEach
Holger

tại sao vậy? bạn có thể giải thích?
Elad Benda2

1
Thực hiện theo các liên kết. Nói một cách đơn giản forEachOrdered, như tên cho thấy, quan tâm đến thứ tự gặp gỡ có liên quan khi bạn muốn bỏ qua một số tệp mới nhất định dựa trên thứ tự sắp xếp theo thứ tự thời gian sửa đổi .
Holger

1
Hơi muộn một chút, tôi muốn thừa nhận rằng sự hiểu biết của bạn về cách sortskip→ (không có thứ tự) forEachnên hoạt động, là chính xác và nó thực sự được thực hiện theo cách này trong các JRE ngày nay, nhưng vào năm 2015, khi các bình luận trước đó được đưa ra, nó đã được đưa ra thực sự là một vấn đề (như bạn có thể đọc trong câu hỏi này ).
Holger

Câu trả lời:


218

Bạn có thể điều chỉnh giải pháp bạn đã liên kết trong Cách sắp xếp ArrayList <Long> theo Java theo thứ tự giảm dần? bằng cách gói nó trong lambda:

.sorted((f1, f2) -> Long.compare(f2.lastModified(), f1.lastModified())

lưu ý rằng f2 là đối số đầu tiên Long.compare, không phải là đối số thứ hai, do đó kết quả sẽ bị đảo ngược.


224
Tiết hayComparator.comparingLong(File::lastModified).reversed()
Holger

3
@Holger Luồng chuỗi và có comparingLong(v->Long.valueOf(v)).reversed()lỗi biên dịch : java.lang.valueOf(java.lang.String) cannot be used on java.lang.valueOf(java.lang.Object). Tại sao?
Tiina

3
@Tiina: xem so sánh.reversed () không biên dịch bằng lambda . Bạn có thể thử comparingLong(Long::valueOf).reversed()thay thế. HoặcCollections.reverseOrder(comparingLong(v->Long.valueOf(v)))
Holger

@Holger cảm ơn vì đường link. Nhưng Stuart "không hoàn toàn chắc chắn tại sao". Tôi đã bối rối khi tôi thấy cả hai phương thức tham chiếu Tthay vì Object, có nghĩa là loại đối tượng không nên bị mất. Nhưng thực tế nó là. Đó là những gì tôi bối rối về.
Tiina

3
@Tiina: đó là sự lan truyền ngược của loại mục tiêu không hoạt động. Nếu biểu thức ban đầu của chuỗi của bạn có loại độc lập, thì nó hoạt động thông qua chuỗi như trước Java 8. Như bạn có thể thấy với ví dụ so sánh, sử dụng tham chiếu phương thức, nghĩa là comparingLong(Long::valueOf).reversed()hoạt động, tương tự như một biểu thức lambda được gõ rõ ràng công trình làm comparingLong((String v) -> Long.valueOf(v)).reversed()việc Cũng Stream.of("foo").mapToInt(s->s.length()).sum()hoạt động, vì "foo"cung cấp loại độc lập trong khi Stream.of().mapToInt(s-> s.length()).sum()thất bại.
Holger

170

Nếu các phần tử luồng của bạn thực hiện Comparablethì giải pháp sẽ trở nên đơn giản hơn:

 ...stream()
 .sorted(Comparator.reverseOrder())

3
hoặc...stream().max(Comparator.naturalOrder())
Philippe

1
Đối với yếu tố gần đây nhất trong bộ sưu tập so sánh theo ngày.stream().max(Comparator.comparing(Clazz::getDate))
Marco Pelegrini

1
Điều gì nếu các yếu tố không Comparable. Collections.reversekhông có hạn chế như vậy.
wilmol

63

Sử dụng

Comparator<File> comparator = Comparator.comparing(File::lastModified); 
Collections.sort(list, comparator.reversed());

Sau đó

.forEach(item -> item.delete());

3
Chà, dù sao thì anh cũng hỏi về stream, nhưng dù sao thì tôi cũng thích câu trả lời của bạn.
Tim Büthe

Đây không phải là cách "chức năng" để làm điều đó ... nó có ảnh hưởng phụ !!
Lập trình viên

38

Bạn có thể sử dụng một tham chiếu phương thức:

import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;

Arrays.asList(files).stream()
    .filter(file -> isNameLikeBaseLine(file, baseLineFile.getName()))
    .sorted(comparing(File::lastModified).reversed())
    .skip(numOfNewestToLeave)
    .forEach(item -> item.delete());

Thay thế cho tham chiếu phương thức, bạn có thể sử dụng biểu thức lambda, do đó, đối số so sánh trở thành:

.sorted(comparing(file -> file.lastModified()).reversed());

19

Cách chia sẻ khác:

TĂNG DẦN

List<Animal> animals = this.service.findAll();
animals = animals.stream().sorted(Comparator.comparing(Animal::getName)).collect(Collectors.toList());

MÔ TẢ

List<Animal> animals = this.service.findAll();
animals = animals.stream().sorted(Comparator.comparing(Animal::getName).reversed()).collect(Collectors.toList());

4

Điều này có thể dễ dàng được thực hiện bằng cách sử dụng Java 8 và việc sử dụng Trình so sánh đảo ngược .

Tôi đã tạo một danh sách các tệp từ một thư mục mà tôi hiển thị chưa sắp xếp, sắp xếp và sắp xếp ngược lại bằng cách sử dụng Bộ so sánh đơn giản để sắp xếp và sau đó gọi đảo ngược () trên đó để lấy phiên bản đảo ngược của Bộ so sánh đó.

Xem mã dưới đây:

package test;

import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

public class SortTest {
    public static void main(String... args) {
        File directory = new File("C:/Media");
        File[] files = directory.listFiles();
        List<File> filesList = Arrays.asList(files);

        Comparator<File> comparator = Comparator.comparingLong(File::lastModified);
        Comparator<File> reverseComparator = comparator.reversed();

        List<File> forwardOrder = filesList.stream().sorted(comparator).collect(Collectors.toList());
        List<File> reverseOrder = filesList.stream().sorted(reverseComparator).collect(Collectors.toList());

        System.out.println("*** Unsorted ***");
        filesList.forEach(SortTest::processFile);

        System.out.println("*** Sort ***");
        forwardOrder.forEach(SortTest::processFile);

        System.out.println("*** Reverse Sort ***");
        reverseOrder.forEach(SortTest::processFile);
    }

    private static void processFile(File file) {
        try {
            if (file.isFile()) {
                System.out.println(file.getCanonicalPath() + " - " + new Date(file.lastModified()));
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

3

Sắp xếp danh sách tệp với Bộ sưu tập java 8

Ví dụ về cách sử dụng Bộ sưu tập và Bộ so sánh Java 8 để sắp xếp danh sách Tệp.

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ShortFile {

    public static void main(String[] args) {
        List<File> fileList = new ArrayList<>();
        fileList.add(new File("infoSE-201904270100.txt"));
        fileList.add(new File("infoSE-201904280301.txt"));
        fileList.add(new File("infoSE-201904280101.txt"));
        fileList.add(new File("infoSE-201904270101.txt"));

        fileList.forEach(x -> System.out.println(x.getName()));
        Collections.sort(fileList, Comparator.comparing(File::getName).reversed());
        System.out.println("===========================================");
        fileList.forEach(x -> System.out.println(x.getName()));
    }
}

1

Nói một cách đơn giản, sử dụng Trình so sánh và Bộ sưu tập, bạn có thể sắp xếp như bên dưới theo thứ tự đảo ngược bằng JAVA 8

import java.util.Comparator;;
import java.util.stream.Collectors;

Arrays.asList(files).stream()
    .sorted(Comparator.comparing(File::getLastModified).reversed())
    .collect(Collectors.toList());

0

Để sắp xếp ngược lại, chỉ cần thay đổi thứ tự của x1, x2 để gọi phương thức x1.compareTo (x2), kết quả sẽ ngược lại với nhau

Thứ tự mặc định

List<String> sortedByName = citiesName.stream().sorted((s1,s2)->s1.compareTo(s2)).collect(Collectors.toList());
System.out.println("Sorted by Name : "+ sortedByName);

Đặt hàng ngược

List<String> reverseSortedByName = citiesName.stream().sorted((s1,s2)->s2.compareTo(s1)).collect(Collectors.toList());
System.out.println("Reverse Sorted by Name : "+ reverseSortedByName );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.