Bagaimana cara menggunakan lambda Java8 untuk mengurutkan aliran dalam urutan terbalik?


181

Saya menggunakan java lambda untuk mengurutkan daftar.

bagaimana saya bisa mengatasinya secara terbalik?

Saya melihat posting ini , tetapi saya ingin menggunakan java 8 lambda.

Ini kode saya (saya menggunakan * -1) sebagai peretasan

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

Apa yang Anda maksud dengan "urutan terbalik"? Jika Anda mengganti -1 * answerdengan answer, pesanan akan berubah untuk membalikkan apa itu dengan -1 * ....
dasblinkenlight

2
Awas! Semua kode Anda menyarankan agar Anda ingin menggunakannya forEachOrderedsebagai gantiforEach
Holger

mengapa demikian? dapatkah kamu menjelaskan
Elad Benda2

1
Ikuti tautannya. Hanya berkata, forEachOrdered, seperti namanya, peduli tentang pesanan pertemuan yang relevan seperti yang Anda ingin melewatkan sejumlah terbaru file yang bergantung pada “diurutkan berdasarkan waktu modifikasi” agar .
Holger

1
Agak terlambat, saya ingin mengakui bahwa pemahaman Anda tentang bagaimana sortskip→ (tidak terurut) forEachharus bekerja, benar dan bahwa memang diterapkan untuk bekerja dengan cara ini di JRE hari ini, tetapi kembali pada tahun 2015, ketika komentar sebelumnya dibuat, itu memang masalah (seperti yang Anda baca dalam pertanyaan ini ).
Holger

Jawaban:


218

Anda dapat menyesuaikan solusi yang Anda tautkan di Cara menyortir ArrayList <Long> di Jawa dalam urutan menurun? dengan membungkusnya dalam lambda:

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

perhatikan bahwa f2 adalah argumen pertama Long.compare, bukan argumen kedua, sehingga hasilnya akan terbalik.


224
… AtauComparator.comparingLong(File::lastModified).reversed()
Holger

3
@Holger Streaming dari String, dan memiliki comparingLong(v->Long.valueOf(v)).reversed()melempar kompilasi error: java.lang.valueOf(java.lang.String) cannot be used on java.lang.valueOf(java.lang.Object). Mengapa?
Tiina

3
@Tiina: lihat Comparator.reversed () tidak dapat dikompilasi menggunakan lambda . Anda dapat mencoba comparingLong(Long::valueOf).reversed()sebagai gantinya. AtauCollections.reverseOrder(comparingLong(v->Long.valueOf(v)))
Holger

@ Holger, terima kasih atas tautannya. Namun Stuart "tidak sepenuhnya yakin mengapa". Saya bingung ketika saya melihat kedua metode merujuk Tbukan Object, artinya jenis objek tidak boleh hilang. Tapi sebenarnya itu. Itulah yang saya bingung.
Tiina

3
@Tiina: ini adalah propagasi balik dari tipe target yang tidak berfungsi. Jika ekspresi awal rantai Anda memiliki tipe yang berdiri sendiri, ia bekerja melalui rantai seperti sebelum Java 8. Seperti yang Anda lihat dengan contoh pembanding, menggunakan referensi metode, yaitu comparingLong(Long::valueOf).reversed()bekerja, juga ekspresi lambda yang diketik secara eksplisit. bekerja comparingLong((String v) -> Long.valueOf(v)).reversed()bekerja. Juga Stream.of("foo").mapToInt(s->s.length()).sum()berfungsi, karena "foo"menyediakan tipe yang berdiri sendiri sedangkan Stream.of().mapToInt(s-> s.length()).sum()gagal.
Holger

170

Jika elemen aliran Anda diterapkan, Comparablemaka solusinya menjadi lebih sederhana:

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

3
atau...stream().max(Comparator.naturalOrder())
Philippe

1
Untuk elemen terbaru dalam koleksi yang membandingkan berdasarkan tanggal.stream().max(Comparator.comparing(Clazz::getDate))
Marco Pelegrini

1
Bagaimana jika elemennya tidak Comparable. Collections.reversetidak memiliki batasan seperti itu.
wilmol

63

Menggunakan

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

Kemudian

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

3
Yah, dia bertanya tentang stream, tapi aku suka jawabanmu.
Tim Büthe

Ini bukan cara "fungsional" untuk melakukannya ... itu punya efek samping !!
Programmer

38

Anda dapat menggunakan referensi metode:

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

Sebagai alternatif referensi metode, Anda dapat menggunakan ekspresi lambda, sehingga argumen pembandingan menjadi:

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

19

Cara berbagi alternatif:

ASC

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

DESC

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

4

Ini dapat dengan mudah dilakukan menggunakan Java 8 dan penggunaan pembanding terbalik .

Saya telah membuat daftar file dari direktori, yang saya tampilkan tidak disortir, diurutkan, dan diurutkan mundur menggunakan pembanding sederhana untuk pengurutan dan kemudian memanggil dibalik () di atasnya untuk mendapatkan versi pembalik pembanding itu.

Lihat kode di bawah ini:

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

Urutkan daftar file dengan Koleksi java 8

Contoh cara menggunakan Collections and Comparator Java 8 untuk mengurutkan daftar File.

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

Secara sederhana, menggunakan Comparator dan Collection Anda dapat mengurutkan seperti di bawah ini dalam urutan pembalikan menggunakan 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

Untuk pemilahan terbalik, cukup ubah urutan x1, x2 untuk memanggil metode x1.compareTo (x2) hasilnya akan terbalik satu sama lain

Pesanan default

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

Urutan terbalik

List<String> reverseSortedByName = citiesName.stream().sorted((s1,s2)->s2.compareTo(s1)).collect(Collectors.toList());
System.out.println("Reverse Sorted by Name : "+ reverseSortedByName );
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.