วิธีใช้แลมบ์ดาของ Java8 เพื่อจัดเรียงสตรีมในลำดับย้อนกลับ


181

ฉันใช้แลมบ์ดา java เพื่อเรียงลำดับรายการ

ฉันจะจัดเรียงมันในทางกลับกันได้อย่างไร

ฉันเห็นโพสต์นี้แต่ฉันต้องการใช้ java 8 แลมบ์ดา

นี่คือรหัสของฉัน (ฉันใช้ * -1) เป็นแฮ็ค

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

คุณหมายถึงอะไรโดย "ย้อนกลับคำสั่งซื้อ"? หากคุณแทนที่-1 * answerด้วยanswerคำสั่งซื้อจะเปลี่ยนกลับเป็นแบบ-1 * ...เดิม
dasblinkenlight

2
ระวัง! รหัสทั้งหมดของคุณแนะนำว่าคุณต้องการใช้forEachOrderedแทนforEach
Holger

ทำไมถึงเป็นอย่างนั้น? คุณสามารถอธิบาย?
Elad Benda2

1
ตามลิงค์ เพียงแค่บอกว่าforEachOrderedเป็นชื่อที่แสดงให้เห็นความกังวลเกี่ยวกับคำสั่งการเผชิญหน้าซึ่งมีความเกี่ยวข้องตามที่คุณต้องการที่จะข้ามไปจำนวนหนึ่งของใหม่ล่าสุดไฟล์ที่อาศัยอยู่กับ“เรียงตามเวลาแก้ไข” เพื่อ
Holger

1
สายไปหน่อยฉันต้องการรับทราบว่าความเข้าใจของคุณเกี่ยวกับวิธีsort→→ skip(ไม่มีการเรียงลำดับ) forEachทำงานถูกต้องและมันถูกนำไปใช้จริงเพื่อทำงานใน JREs วันนี้ แต่ย้อนกลับไปในปี 2015 เมื่อความคิดเห็นก่อนหน้านี้เกิดขึ้น เป็นปัญหาอย่างแน่นอน (ตามที่คุณอาจอ่านในคำถามนี้ )
Holger

คำตอบ:


218

คุณสามารถปรับแก้ปัญหาที่คุณเชื่อมโยงในวิธีการเรียงลำดับ ArrayList <Long> ใน Java ในลำดับที่ลดลง? โดยห่อไว้ในแลมบ์ดา:

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

โปรดทราบว่าf2เป็นอาร์กิวเมนต์แรกของLong.compareไม่ใช่วินาทีดังนั้นผลลัพธ์จะกลับด้าน


224
…หรือComparator.comparingLong(File::lastModified).reversed()
Holger

3
@Holger กระแสสตริงและมีพ่นรวบรวมข้อผิดพลาด:comparingLong(v->Long.valueOf(v)).reversed() java.lang.valueOf(java.lang.String) cannot be used on java.lang.valueOf(java.lang.Object)ทำไม?
Tiina

3
@Tiina: ดูComparator.reversed () ไม่ได้รวบรวมโดยใช้แลมบ์ดา คุณอาจลองcomparingLong(Long::valueOf).reversed()แทน หรือCollections.reverseOrder(comparingLong(v->Long.valueOf(v)))
โฮลเกอร์

@ Holger ขอบคุณสำหรับลิงค์ แต่สจ๊วร์ต "ไม่แน่ใจว่าทำไม" ฉันสับสนเมื่อฉันเห็นการอ้างอิงทั้งสองวิธีTแทนObjectความหมายประเภทของวัตถุไม่ควรสูญหาย แต่จริงๆแล้วมันคือ นั่นคือสิ่งที่ฉันสับสน
Tiina

3
@Tiina: มันเป็นการขยายพันธุ์กลับของประเภทเป้าหมายที่ไม่ทำงาน หากการแสดงออกเริ่มต้นของห่วงโซ่ของคุณมีประเภทแบบสแตนด์อะโลนก็จะทำงานผ่านห่วงโซ่เหมือนที่ทำไว้ก่อนหน้า Java 8 ดังที่คุณสามารถดูด้วยตัวอย่างเปรียบเทียบโดยใช้การอ้างอิงวิธีการเช่นการcomparingLong(Long::valueOf).reversed()ทำงานเช่นการแสดงออกแลมบ์ดาพิมพ์ชัดเจน ผลcomparingLong((String v) -> Long.valueOf(v)).reversed()งาน ใช้Stream.of("foo").mapToInt(s->s.length()).sum()งานได้เช่นกันเนื่องจาก"foo"มีประเภทสแตนด์อะโลนขณะที่Stream.of().mapToInt(s-> s.length()).sum()ล้มเหลว
Holger

170

หากองค์ประกอบการสตรีมของคุณใช้งานComparableโซลูชันจะง่ายขึ้น:

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

3
หรือ...stream().max(Comparator.naturalOrder())
Philippe

1
สำหรับองค์ประกอบล่าสุดในคอลเลกชันเปรียบเทียบตามวันที่.stream().max(Comparator.comparing(Clazz::getDate))
Marco Pelegrini

1
Comparableเกิดอะไรขึ้นถ้าองค์ประกอบไม่ได้ Collections.reverseไม่มีข้อ จำกัด ดังกล่าว
wilmol

63

ใช้

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

แล้วก็

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

3
เขาถามถึงลำธาร แต่ฉันชอบคำตอบของคุณ
ทิมBüthe

นี่ไม่ใช่วิธีการ "ใช้งานได้" ในการทำมัน ... มันมีผลข้างเคียง !!
โปรแกรมเมอร์

38

คุณสามารถใช้การอ้างอิงวิธีการ:

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

ในทางเลือกอื่นของการอ้างอิงวิธีการคุณสามารถใช้แลมบ์ดานิพจน์ดังนั้นข้อโต้แย้งของการเปรียบเทียบกลายเป็น:

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

19

การแบ่งปันทางเลือก:

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

สิ่งนี้สามารถทำได้อย่างง่ายดายโดยใช้ Java 8 และการใช้สิ่งที่ตรงกันข้าม เปรียบเทียบ

ฉันสร้างรายการไฟล์จากไดเรกทอรีซึ่งฉันแสดงเรียงลำดับเรียงลำดับและย้อนกลับโดยใช้เครื่องมือเปรียบเทียบอย่างง่ายสำหรับการเรียงลำดับแล้วเรียกกลับรายการ () บนเพื่อรับเวอร์ชันที่ตรงกันข้ามของตัวเปรียบเทียบนั้น

ดูรหัสด้านล่าง:

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

เรียงลำดับรายการไฟล์ด้วย java 8 Collections

ตัวอย่างวิธีใช้ Collections และ Comparator Java 8 เพื่อเรียงลำดับรายการไฟล์

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

ง่าย ๆ โดยใช้ Comparator และ Collection คุณสามารถเรียงลำดับด้านล่างตามลำดับการกลับรายการโดยใช้ 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

สำหรับการเรียงลำดับแบบย้อนกลับเพียงแค่เปลี่ยนลำดับของ x1, x2 สำหรับการเรียกวิธีการ x1.compareTo (x2) ผลที่ได้จะกลับกัน

คำสั่งซื้อเริ่มต้น

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

สั่งซื้อย้อนกลับ

List<String> reverseSortedByName = citiesName.stream().sorted((s1,s2)->s2.compareTo(s1)).collect(Collectors.toList());
System.out.println("Reverse Sorted by Name : "+ reverseSortedByName );
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.