Loading...
simeon_petrov avatar simeon_petrov 45 Точки

Java Basics Functional Programming and Stream API сортиране по два критерия.

Вдъхновен от домашното за функционално програмиране на Java, ето тук: https://softuni.bg/downloads/svn/java-basics/Mar-2016/5.Functional-Programming-and-StreamAPI-Homework.docx

Реших да направя на Java домашното по функционално програмиране от курса по Advanced C#, ето тук: https://softuni.bg/downloads/svn/csharp-advanced/Feb-2016/4.%20Advanced-CSharp-Functional-Programming-Homework.zip

Добутах ги до 5та задача, ето ми решенията:  http://pastebin.com/6A073vyr

а това е класът Student: http://pastebin.com/ZmbKqmXP

Въпросът ми е, как да сортирам студентите първо по firstName, а след това по lastName? Опитвам се да използвам Lambda expressions от java 8, това което на някои места го наричат "нов начин", щото има и "стар начин" и той май е малко по-дървен.

Та примерно:

studentsCopy.sort(((s1, s2) -> s2.getFirstName().compareTo(s1.getFirstName())));
studentsCopy.forEach(s -> System.out.println(s.getFirstName() + " " + s.getLastName()));

Това ми ги сортира по първо име в низходящ ред, ама как сега да ги сортира и по фамилия?

0
Java Advanced
RoYaL avatar RoYaL Trainer 6849 Точки

Здравей,

За да разбереш как да сортираш подавайки "начин" на сортиране, трябва да разбереш как работят сортиращите алгоритми по принцип.

Нека си представим най-простия и най-дървен сортиращ алгоритъм (много бавен), където искаш да сортираш в низходящ ред. За целта трябва да сложиш най-големия елемент най-в ляво, после втория най-голям и т.н.

За да намериш най-големия елемент, минаваш през всички елементи и сравняваш всеки един елемент с най-големия до момента. После трябва да направиш тва за всеки следващ елемент.
 

while (start < length) {

     int max = MIN_VALUE;

     for (int i = start; i < length; i++) {

         if (arr[i] > max) max = arr[i]

     }

     newArr[start] = max;

     start++

}

Тук можеш да забележиш, че ти трябват две променливи - arr[i] => елемент от масива и max => най-големия до момента елемент. Това са двете, които се сравняват.

Сега си представи, че този масив не е от числа, а от обекти. За да се сравнява по комплексни типове, трябва последните да предоставят възможност за оценка на теглото си. Т.е. дали един от обект от този тип, е по-голям от обект от същия тип, по-малък или еднакво "тежък". Този начин е методът Object1.compareTo(Object2). Това притегляне се извиква в тялото на иф-а

вместо if(arr[i] > max) става if(arr[i].compareTo(max) > 0)

Когато използваш sorted(lambda) или sort(lambda) това, което става е, че този compareTo не се взима под внимание, а се взима този, който ти ще напишеш в тялото на sort(). Ще се вземе целия този код, който ти напишеш и ще се сложи в if-a.

Т.е. ако искаш да сложиш един елемент най-от ляво (считайки го за най-голям) по два критерия, трябва да кажеш, че вторият (max) е по-тежък от първия (arr[i]) само когато и firstName-а и lastName-а му са по-големи. Това означава, че трябва да извикаш притеглянето на lastName, само когато притеглянето на firstName е върнало нула (равенство)
 

if (s2.firstName.compareTo(s1.firstName) == 0) {

    return s2.lastName.compareTo(s1.lastName); // тук ако и второто име е равно, пак ще върне че двата са равни, иначе ще ги притегли по втория критерий

}

return s2.firstName.compareTo(s1.firstName); //  ако не са равни първите имена е достатъчно да сортира само по тях

Това можеш да го сложиш в тялото на ламбдата, ако я оградиш в къдрави скоби, тъй като не е едноредова.

Ако има нещо, което не е станало ясно, нека продължим дискусията. Ще ми се да се изяснят нещата отвътре, вместо просто да се копира някакъв код :)

Поздрави,

Иван

 

 

4
simeon_petrov avatar simeon_petrov 45 Точки

Благодаря много за отговора, добре си го описал и го разбрах! Схванах идеята, приложих я и стана. Да попитам и още нещо, по същата логика тръгнах да решавам следния проблем:  extract the students with exactly two marks "2". С две думи, студентите имат List с оценки и трябва да изкарам име, фамилия и оценките само на тези, които имат по две двойки.

Ей така го направих, кажете дали е добре или има и по-готин начин.

studentsCopy.forEach(s -> {
if (weekStudentOrNot(s.getMarks())) {
 System.out.println(s.getFirstName()+" "+s.getLastName()+" "+s.getMarks());
            }
        }
);

и отдолу има една функцийка - private static boolean weekStudentOrNot(List<Integer> arr), която има  for цикъл вътре и връща true, ако има две двойки и false при всички други случаи.

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.