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

Znalezienie pięciu największych liczb w liście
KA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 27
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());
}
}
_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
1

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

Kopiuj
      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

ZD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2310
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 ?

Kopiuj
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ć

LitwinWileński
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 764
1

nazwy!

KA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 27
0
Kopiuj
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:

Kopiuj
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Comparable.compareTo(Object)" because "c2" is null
jarekr000000
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: U krasnoludów - pod górą
  • Postów: 4714
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.

KA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 27
0
Kopiuj
    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ć ?

K5
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1005
0
KotAli napisał(a):
Kopiuj
        
        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.

LitwinWileński
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 764
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.

_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
0
Kopiuj
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.

W0
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3760
1
KotAli napisał(a):
Kopiuj
    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.

Kopiuj
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;

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.