Znalezienie pięciu największych liczb w liście

0

Hej musze znaleźć 5 największych liczb z listy. List<Integer> może być różna np: wypełniona null-ami, może być pusta, może być za mało liczb, a może też być okey. Poniżej kod - jest okey da się go uprościć coś można ulepszyć jakieś wskazówki ?. Optional i .stream() wykorzystać. jak coś będzie nie tak to zwrócić psutą listę. Z góry dzięki

    List<Integer> firstList = new ArrayList<>();
    firstList.add(null);
    firstList.add(null);
    firstList.add(null);
    firstList.add(null);
    firstList.add(null);

    List<Integer> secondList = new ArrayList<>();
    secondList.add(23);
    secondList.add(null);
    secondList.add(222);
    secondList.add(17);

    List<Integer> thirdList = new ArrayList<>();
    thirdList.add(2);
    thirdList.add(null);
    thirdList.add(3);
    thirdList.add(3);
    thirdList.add(3);
    thirdList.add(3);
    thirdList.add(3);
    thirdList.add(3);

    List<Integer> emptyList = new ArrayList<>();

    System.out.println(fiveBigestNumber(firstList));
    System.out.println(fiveBigestNumber(secondList));
    System.out.println(fiveBigestNumber(thirdList));
    System.out.println(fiveBigestNumber(emptyList));


public static List<Integer> fiveBigestNumber(List<Integer> integerList) { //wywoałenie metody trialClassInteger , musi być >= 5 elementów jak nie to pusta lista
    return Optional.ofNullable(integerList)
            .map(Main2::trialClassInteger)
            .filter(data -> data.size() >= 5)
            .orElseGet(Collections::emptyList);

}

public static List<Integer> trialClassInteger(List<Integer> integerList) { // usuniecie nulli, od największej do najmniejszej, max 5 liczb i do listy 
    return integerList.stream()
            .filter(Objects::nonNull)
            .sorted(Comparator.reverseOrder())
            .limit(5)
            .collect(Collectors.toList());
}
}
1

Pierwsza część to można prościej:

      List<Integer> firstList=Arrays.asList(null,null,null,null,null);
      List<Integer> secondList=Arrays.asList(23,null,222,17);
      List<Integer> thirdList=Arrays.asList(2,null,3,3,3,3,3,3);
      List<Integer> emptyList=Arrays.asList();

Natomiast w drugiej wg mnie jest błąd, bo nie zwróci ci tablicy większej niż 5 elementów, zaś w komentarzu widzę musi być >= 5 elementów

2

To ja się wypowiem nt dołu :)

Strasznie nierówny ten kod jest. Co jest twoje, a co pożyczone, ale bez kręcenia ?

public static List<Integer> fiveBigestNumber(List<Integer> integerList) { //wywoałenie metody trialClassInteger , musi być >= 5 elementów jak nie to pusta lista
    return Optional.ofNullable(integerList)
            .map(Main2::trialClassInteger)
            .filter(data -> data.size() >= 5)
            .orElseGet(Collections::emptyList);

}

a) Z zadania nie wynika, ze argument listowy może być null (lista pusta to coś innego niż lista null), a tu idzie energia w sztuczne wytwarzanie Optionala
b) .map(Main2::trialClassInteger) no sorry, ale cały romantyzm upada w jednej chwili, jak widzę ten Main2 ... metoda w Main ... to tak jakby prawie nie metoda, to ani nie OOP, ani funkcyjne.
c) w konsekwencji (chyba) nie przemyślenia a), orElseGet jest warunkiem ustawionym na coś innego niż miało być

1

nazwy!

0
List<Integer> list1 = Arrays.asList(2, 0, 3, 12, 122);
List<Integer> list2 = Arrays.asList(2, 0, 3, 122);
List<Integer> list3 = Arrays.asList();
List<Integer> list4 = Arrays.asList(null,null,null,null,null);
List<Integer> list5 = Arrays.asList(12,23,42,42,null,null,32);
System.out.println(integerList(list1));
System.out.println(integerList(list2));
System.out.println(integerList(list3));
System.out.println(integerList(list4));
System.out.println(integerList(list5));

      
public static List<Integer> integerList(List<Integer> integerList) {
    return Optional.ofNullable(integerList)
            .filter(data -> data.size() >= 5)
            .orElseGet(Collections::emptyList)
            .stream()
            .sorted(Comparator.reverseOrder())
            .limit(5)
            .collect(Collectors.toList());
}

Update kodu. Wszystko działa oprócz wyłapania nulli. Jak sobie z tym poradzić ? Lista jest opakowana w Optionala ale i tak nie chce pozbyć się tych nulli; Tak jakby wartość null przechodzą dalej do stream-a. Błąd:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Comparable.compareTo(Object)" because "c2" is null
1

W treści zadania nie było, że lista może być nullem (było, że pusta, wypełniona nullami itp.).

Uważam, że przy podawaniu nulla jako argument należy zwracać odpowiednią informację, którą to jest NullPointerException. Co fajne - JVM sam to zrobi.
Chodzi o to, żeby nie robić nonsensowenych null checków (wpakowywanie w optionala (ofNullable) też pod to podchodzi).
Inaczej lądujemy z kodem, którego połowa to jakieś sprawdzanie nulli i trudno się przez ten szum przebija.

Oczywiście nie wszędzie można pomijać sprawdzanie null - np. jeśli input pochodzi z zewnątrz (front albo robimy bibliotekę) to wtedy na poziomie fasad takie nadmiarowe sprawdzanie null, walidacja ma jakiś sens.

0
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>(Arrays.asList(2, 0, 3, 12, 122));
        List<Integer> list2 = new ArrayList<>(Arrays.asList(2, 0, 3, 122));
        List<Integer> list3 = new ArrayList<>(Arrays.asList(null, null, null, null, null, null));
        List<Integer> list4 = new ArrayList<>(Arrays.asList(null, null, 12, 23, 42, 32));

        System.out.println(integerList(list1));
        System.out.println(integerList(list2));
        System.out.println(integerList(list3));
        System.out.println(integerList(list4));
    }

    public static List<Integer> integerList(List<Integer> integerList) {
        List<Integer> collect = Optional.ofNullable(integerList)
                .filter(data -> data.size() >= 5)  //jeśli lista ma mniej niż 5 elementów to od razu emptyList;
                .orElseGet(Collections::emptyList) 
                .stream()
                .filter(Objects::nonNull) // wywalenie null-i
                .sorted(Comparator.reverseOrder()) //sortowanie od największej do najmniejszej 
                .limit(5) // tylko 5 elementów
                .collect(Collectors.toList()); // do zapisanie do listy
        
        if (collect.size() == 5) { // zabezpieczenie może być tak że jest (2,5,12,null,null) i wtedy przejdzie do streama 
                                      i bez tego wywaliłoby 3 elementy tylko na liście a potrzebujemy 5;
            return collect;
        } else {
            return new ArrayList<>();
        }
    }

result:
fiveBigesstNumber.PNG

Update: Można jeszcze bardziej poprawić/ulepszyć/skrócić ten kod ? Kod działa jednak czy można go ulepszyć ?

0
KotAli napisał(a):
        
        if (collect.size() == 5) { // zabezpieczenie może być tak że jest (2,5,12,null,null) i wtedy przejdzie do streama 
                                      i bez tego wywaliłoby 3 elementy tylko na liście a potrzebujemy 5;
            return collect;
        } else {
            return new ArrayList<>();
        }
    }

Ta końcowka i to wytłumaczenie jest dziwne.
Czyli co, jak nie znaleźliśmy 5 liczb, tylko 3 bo lista wejściowa miała 3 elementy to wynikiem będzie pusta lista bo koniecznie musi być 5 liczb w rezultacie? To jest jakieś głupie.

0

nie ifuj filtrem.
raz wyrzucasz Collections.emptyList() a raz new ArrayList<>()
skoro ma być min. 5 elementów nienullowych to daj ifa, żeby było min. 5 elementów nienulowych, a nie sprawdzasz to po 2 razy: najpierw czy min. 5 elementów i po obliczeniach jeszcze raz sprawdzasz czy nie ma mniej.

0
public class OptionalTest
{
   public static void main(String[] args)
   {
      List<List<Integer>> lists=Arrays.asList
      (
         Arrays.asList(2,0,3,12,122),
         Arrays.asList(2,0,3,122),
         Arrays.asList(null,null,null,null,null,null),
         Arrays.asList(3,null,null,12,23,42,32),
         Arrays.asList(null,null,12,23,42,32)
      );

      for(List<Integer> lst:lists) System.out.println(integerList(lst));
   }

   public static List<Integer> integerList(List<Integer> input)
   {
      //input=(input==null?Arrays.asList():input);
      input=input.stream().filter(Objects::nonNull).sorted(Comparator.reverseOrder()).limit(5).collect(Collectors.toList());
      return input.size()<5?Arrays.asList():input;
   }
}

W zasadzie wiersz 19 należy wywalić bo ma walić wyjątkiem przy null zamiast tablicy, zresztą @jarekr000000 ma takie same zdanie.

1
KotAli napisał(a):
    public static List<Integer> integerList(List<Integer> integerList) {
        List<Integer> collect = Optional.ofNullable(integerList)
                .filter(data -> data.size() >= 5)  //jeśli lista ma mniej niż 5 elementów to od razu emptyList;
                .orElseGet(Collections::emptyList) 
                .stream()
                .filter(Objects::nonNull) // wywalenie null-i
                .sorted(Comparator.reverseOrder()) //sortowanie od największej do najmniejszej 
                .limit(5) // tylko 5 elementów
                .collect(Collectors.toList()); // do zapisanie do listy
        
        if (collect.size() == 5) { // zabezpieczenie może być tak że jest (2,5,12,null,null) i wtedy przejdzie do streama 
                                      i bez tego wywaliłoby 3 elementy tylko na liście a potrzebujemy 5;
            return collect;
        } else {
            return new ArrayList<>();
        }
    }

Nie ma co bawić się w Optionala.

List<Integer> result = Stream.of(integerList)
   .filter(Objects::nonNull)
   .flatMap(List::stream)
   .filter(Objects::nonNull)
   .sorted(Comparator.reverseOrder())
   .limit(5)
   .collect(Collectors.toList());

return result.size() < 5 ? Collections.emptyList() : result;

1 użytkowników online, w tym zalogowanych: 0, gości: 1