Sortowanie listy za pomocą stream.sorted () w Javie

96

Jestem zainteresowany sortowaniem listy ze strumienia. Oto kod, którego używam:

list.stream()
    .sorted((o1, o2)->o1.getItem().getValue().compareTo(o2.getItem().getValue()))
    .collect(Collectors.toList());

Czy coś mi brakuje? Lista nie jest sortowana.

Powinien posortować listy według pozycji o najniższej wartości.

for (int i = 0; i < list.size(); i++)
{
   System.out.println("list " + (i+1));
   print(list, i);
}

Oraz metoda druku:

public static void print(List<List> list, int i)
{
    System.out.println(list.get(i).getItem().getValue());
}
Ivan C.
źródło

Odpowiedzi:

147

To nie jest tak, jak w Collections.sort()przypadku sortowania odniesienia do parametru. W tym przypadku po prostu otrzymasz posortowany strumień, który musisz zebrać i ostatecznie przypisać do innej zmiennej:

List result = list.stream().sorted((o1, o2)->o1.getItem().getValue().
                                   compareTo(o2.getItem().getValue())).
                                   collect(Collectors.toList());

Właśnie przegapiłeś przypisanie wyniku

Matt
źródło
67

Użyj list.sortzamiast tego:

list.sort((o1, o2) -> o1.getItem().getValue().compareTo(o2.getItem().getValue()));

i uczyń go bardziej zwięzłym, używając Comparator.comparing:

list.sort(Comparator.comparing(o -> o.getItem().getValue()));

Po jednym z nich listsam zostanie posortowany.

Twój problem polega na tym, że zwraca posortowane dane, a nie sortuje w miejscu, jakiego oczekujesz.list.stream.sorted

Rzeka
źródło
5
list.sort(Comparator.comparing(o -> o.getItem().getValue()));było dla mnie nowe. Świetny!
Neuron
36

Java 8 udostępnia różne narzędzia API, które pomagają nam lepiej sortować strumienie.

Jeśli Twoja lista jest listą liczb całkowitych (lub podwójną, długą, ciągową itp.), Możesz po prostu posortować listę za pomocą domyślnych komparatorów dostarczonych przez java.

List<Integer> integerList = Arrays.asList(1, 4, 3, 4, 5);

Tworzenie komparatora w locie:

integerList.stream().sorted((i1, i2) -> i1.compareTo(i2)).forEach(System.out::println);

Z domyślnym komparatorem udostępnianym przez java 8, gdy żaden argument nie został przekazany do funkcji sort ():

integerList.stream().sorted().forEach(System.out::println); //Natural order

Jeśli chcesz posortować tę samą listę w odwrotnej kolejności:

 integerList.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println); // Reverse Order

Jeśli Twoja lista jest listą obiektów zdefiniowanych przez użytkownika, to:

List<Person> personList = Arrays.asList(new Person(1000, "First", 25, 30000),
        new Person(2000, "Second", 30, 45000),
        new Person(3000, "Third", 35, 25000));

Tworzenie komparatora w locie:

personList.stream().sorted((p1, p2) -> ((Long)p1.getPersonId()).compareTo(p2.getPersonId()))
        .forEach(person -> System.out.println(person.getName()));

Korzystanie z metody Comparator.comparingLong () (mamy też metody comparingDouble (), comparingInt ()):

personList.stream().sorted(Comparator.comparingLong(Person::getPersonId)).forEach(person -> System.out.println(person.getName()));

Korzystanie z metody Comparator.comparing () (metoda Generic, która porównuje na podstawie dostarczonej metody pobierającej):

personList.stream().sorted(Comparator.comparing(Person::getPersonId)).forEach(person -> System.out.println(person.getName()));

Możemy też zrobić łańcuch przy użyciu metody thenComparing ():

personList.stream().sorted(Comparator.comparing(Person::getPersonId).thenComparing(Person::getAge)).forEach(person -> System.out.println(person.getName())); //Sorting by person id and then by age.

Klasa osoby

public class Person {
    private long personId;
    private String name;
    private int age;
    private double salary;

    public long getPersonId() {
        return personId;
    }

    public void setPersonId(long personId) {
        this.personId = personId;
    }

    public Person(long personId, String name, int age, double salary) {
        this.personId = personId;
        this.name = name;
        this.age = age;

        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}
Udaya Shankara Gandhi Thalabat
źródło
4
Wydaje mi się, że ta odpowiedź jest zbyt szczegółowa, aby odpowiedzieć na to pytanie, a mimo to w ogóle jej nie dotyczy. Zamiast tego rozważ użycie tej odpowiedzi w pytaniach, na które odpowiedziano samodzielnie.
Rzeka
1
Uważam też, że to najlepsza i poprawna odpowiedź. używanie Comparator.comparing*jest sposobem lepszym i bardziej zorientowanym na
JDK8
0

Wygląda na to, że działa dobrze:

List<BigDecimal> list = Arrays.asList(new BigDecimal("24.455"), new BigDecimal("23.455"), new BigDecimal("28.455"), new BigDecimal("20.455"));
System.out.println("Unsorted list: " + list);
final List<BigDecimal> sortedList = list.stream().sorted((o1, o2) -> o1.compareTo(o2)).collect(Collectors.toList());
System.out.println("Sorted list: " + sortedList);

Przykładowe wejście / wyjście

Unsorted list: [24.455, 23.455, 28.455, 20.455]
Sorted list: [20.455, 23.455, 24.455, 28.455]

Czy na pewno nie weryfikujesz listy zamiast sortedList[w powyższym przykładzie], tj. Przechowujesz wynik stream()w nowym Listobiekcie i weryfikujesz ten obiekt?

Tanmay Baid
źródło
0
Collection<Map<Item, Integer>> itemCollection = basket.values();
Iterator<Map<Item, Integer>> itemIterator =   itemCollection.stream().sorted(new TestComparator()).collect(Collectors.toList()).iterator();



package com.ie.util;

import com.ie.item.Item;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class TestComparator implements Comparator<Map<Item, Integer>> {

// comparator is used to sort the Items based on the price


    @Override
    public int compare(Map<Item, Integer> o1, Map<Item, Integer> o2) {


      //  System.out.println("*** compare method will be called *****");


        Item item1 = null;
        Item item2 = null;


        Set<Item> itemSet1 = o1.keySet();
        Iterator<Item> itemIterator1 = itemSet1.iterator();
        if(itemIterator1.hasNext()){
           item1 =   itemIterator1.next();
        }

        Set<Item> itemSet2 = o2.keySet();
        Iterator<Item> itemIterator2 = itemSet2.iterator();
        if(itemIterator2.hasNext()){
            item2 =   itemIterator2.next();
        }


        return -item1.getPrice().compareTo(item2.getPrice());


    }
}

**** jest to pomocne przy sortowaniu zagnieżdżonych obiektów mapy, takich jak Mapa> tutaj posortowałem według ceny obiektu.

Venkat IndianEagle
źródło
0

Oto prosty przykład:

List<String> citiesName = Arrays.asList( "Delhi","Mumbai","Chennai","Banglore","Kolkata");
System.out.println("Cities : "+citiesName);
List<String> sortedByName = citiesName.stream()
                .sorted((s1,s2)->s2.compareTo(s1))
                        .collect(Collectors.toList());
System.out.println("Sorted by Name : "+ sortedByName);

Może się zdarzyć, że twoje IDE nie pobiera jdk 1.8 lub wyższej wersji do kompilacji kodu.

Ustaw wersję Java 1.8 dla Your_Project > properties> Project Facets> Java w wersji 1.8

Jimmy
źródło