Commit edd2f93f by Patryk Czarnik

Reszta przykładów EMPS

parent 1042c4ff
package emps;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class F9_Partycje {
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
// Podział rekordów na dwie części i zapisanie w słowniku,
// w którym kluczem są wartości true/false
Map<Boolean, List<Employee>> grupy = emps.stream()
.collect(Collectors.partitioningBy(emp -> emp.getSalary() >= 10_000));
System.out.println("Bogaci:");
grupy.get(true).forEach(emp -> {
System.out.printf(" * %s %s (%s), pensja: %s\n", emp.getFirstName(), emp.getLastName(), emp.getJobTitle(), emp.getSalary());
});
System.out.println("\nBiedni:");
grupy.get(false).forEach(emp -> {
System.out.printf(" * %s %s (%s), pensja: %s\n", emp.getFirstName(), emp.getLastName(), emp.getJobTitle(), emp.getSalary());
});
}
}
package emps;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class FGrupowanie1 {
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
Map<String, List<Employee>> grupy = emps.stream().collect(Collectors.groupingBy(Employee::getJobTitle));
// groupingBy wywołany w najprostszy sposób daje w wyniku słownik, w którym
// dla określonej wartości klucza (np. "Programmer") zapisana jest lista wszystkich rekordów, które należą do tej grupy
// Zawartość słownika przejrzymy w sposób oparty o wyrażenia lambda, operacją forEach
grupy.forEach((job, lista) -> {
System.out.println("Pracownicy typu " + job + ":");
lista.forEach(emp -> {
System.out.println(" * " + emp.getFirstName() + " " + emp.getLastName());
});
System.out.println();
});
}
}
package emps;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class FGrupowanie2 {
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
// Jeśli do groupingBy jako drugi parametr przekażemy kolektor, to mówi on "co zrobić z każdą grupą".
// Przykładowo liczymy średnią pensję pracowników w grupie.
Map<String, Double> grupy = emps.stream()
.collect(Collectors.groupingBy(Employee::getJobTitle,
Collectors.averagingInt(Employee::getSalary)));
grupy.forEach((job, srednia) -> {
System.out.printf("%-32s → %8.2f\n", job, srednia);
});
}
}
package emps;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class FGrupowanie3 {
// W tej wersji dla każdej grupy wyliczamy "statystyki".
// Niezależnie od tego do kolektora groupingBy przekazuję też parametr TreeMap::new
// co powoduje użycie TreeMap zamiast HashMap
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
Map<String, IntSummaryStatistics> grupy = emps.stream()
.collect(Collectors.groupingBy(Employee::getJobTitle,
TreeMap::new, // () -> new TreeMap()
Collectors.summarizingInt(Employee::getSalary)));
// grupy.forEach((job, statystyki) -> System.out.printf("%-32s → %s\n", job, statystyki));
grupy.forEach((job, stats) -> System.out.printf("| %-32s | %2d | %5d | %8.2f | %5d |%n",
job, stats.getCount(), stats.getMin(), stats.getAverage(), stats.getMax()));
}
}
package emps;
import java.util.List;
public class Filtrowanie {
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
emps.stream()
.filter(emp -> emp.getSalary() >= 10000)
.filter(emp -> emp.getCity().startsWith("S"))
.forEach(emp -> System.out.println(emp.getFirstName()
+ " " + emp.getLastName() + " z miasta " + emp.getCity()
+ " zarabia " + emp.getSalary()));
}
}
package emps;
import java.util.List;
public class FiltrowanieMapowanie {
// Ten zapis to jest tzw. "pipeline", na który składają się:
// - źródło (w tym przypadku emps.stream() - źródłem danych jest lista)
// - operacje pośrednie (intermediate operations) - tutaj najbardziej typowe, czyli filter i map
// - operacja końcowa (terminal operation) - tutaj jest to forEach
// Ważny szczegół: w pewnym miejscu zmienia się typ danych. Najpierw jest to strumień Employees,
// a za pierwszym map pojawia się strumień Stringów
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
emps.parallelStream()
.filter(emp -> emp.getSalary() < 10000)
.map(emp -> emp.getFirstName() + " " + emp.getLastName() +
" z miasta " + emp.getCity() + " zarabia " + emp.getSalary())
.filter(s -> s.contains("K")) // .map(s -> s.toUpperCase())
.map(String::toUpperCase)
//.forEach(System.out::println);
.findAny().ifPresent(System.out::println);
}
}
package emps;
import java.util.List;
public class FiltrowanieMapowanie_JakoPetla {
// Ta sama logika, co w programie FiltrowanieMapowanie , ale zapisana za pomocą zwykłych pętli i ifów
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
for(Employee emp : emps) {
if(emp.getSalary() >= 10000) {
String s = emp.getFirstName() + " " + emp.getLastName() +
" z miasta " + emp.getCity() + " zarabia " + emp.getSalary();
if(s.contains("K")) {
String s2 = s.toUpperCase();
System.out.println(s2);
}
}
}
}
}
package emps;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Grupowanie1 {
// W tej wersji najpierw ustalamy, jakie są joby, a następnie dla każdego joba od nowa przeglądamy dane
// To nie jest optymalne pod kątem wydajności.
// Mając 19 jobów i 107 pracowników, tę linię, w której jest if wykonamy aż 19×107 razy.
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
// etap 1: zbieramy nazwy jobów bez powtórzeń
Set<String> jobs = new HashSet<>();
for(Employee emp : emps) {
jobs.add(emp.getJobTitle());
}
// etap 2: dla każdego joba przeglądamy listę empsów i wybieramy tych pracowników, którzy mają taki job
for(String job : jobs) {
double suma = 0;
int ile = 0;
for(Employee emp : emps) {
if(emp.getJobTitle().equals(job)) {
suma += emp.getSalary();
ile++;
}
}
double srednia = suma / ile;
System.out.printf("%-32s | %2d | %8.2f\n", job, ile, srednia);
}
}
}
package emps;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Grupowanie2 {
// Tutaj mamy pokazany standardowy schemat "grupowania za pomocą słowników".
// Używamy poleceń dostepnych w tej formie od Javy 5.
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
Map<String, Integer> sumy = new HashMap<>();
Map<String, Integer> ilosci = new HashMap<>();
for(Employee emp : emps) {
if(sumy.containsKey(emp.getJobTitle())) {
// to jest kolejny pracownik z tego stanowiska → zwiększamy wartość w słowniku
int suma = sumy.get(emp.getJobTitle());
sumy.put(emp.getJobTitle(), suma + emp.getSalary());
int ile = ilosci.get(emp.getJobTitle());
ilosci.put(emp.getJobTitle(), ile + 1);
} else {
// to jest pierwszy pracownik z tego stanowiska → wpisujemy jego pensję jako wartość początkową
sumy.put(emp.getJobTitle(), emp.getSalary());
ilosci.put(emp.getJobTitle(), 1);
}
}
// System.out.println(sumy);
for(String job : sumy.keySet()) {
int ile = ilosci.get(job);
int suma = sumy.get(job);
double srednia = (double)suma / ile;
System.out.printf("%-32s | %2d | %8.2f\n", job, ile, srednia);
}
}
}
package emps;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Grupowanie2a {
public static void main(String[] args) {
final List<Employee> emps = ObslugaCSV.wczytaj();
final Map<String, Integer> sumy = new HashMap<>();
final Map<String, Integer> ilosci = new HashMap<>();
for(Employee emp : emps) {
final String jobTitle = emp.getJobTitle();
if(sumy.containsKey(jobTitle)) {
// to jest kolejny pracownik z tego stanowiska → zwiększamy wartość w słowniku
int suma = sumy.get(jobTitle);
sumy.put(jobTitle, suma + emp.getSalary());
int ile = ilosci.get(jobTitle);
ilosci.put(jobTitle, ile + 1);
} else {
// to jest pierwszy pracownik z tego stanowiska → wpisujemy jego pensję jako wartość początkową
sumy.put(jobTitle, emp.getSalary());
ilosci.put(jobTitle, 1);
}
}
for(String job : sumy.keySet()) {
int ile = ilosci.get(job);
int suma = sumy.get(job);
double srednia = (double)suma / ile;
System.out.printf("%-32s | %2d | %8.2f\n", job, ile, srednia);
}
}
}
package emps;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class Grupowanie3 {
// W wersjach 3-5 używamy nowych operacji słowników, które pojawiły się w Javie 8.
// getOrDefault - w razie braku danych zwraca podaną wartość domyślną
// Pzy okazji używamy LinkedHashMap - zachowuje oryginalną kolejność
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
Map<String, Integer> sumy = new LinkedHashMap<>();
Map<String, Integer> ilosci = new LinkedHashMap<>();
for(Employee emp : emps) {
int suma = sumy.getOrDefault(emp.getJobTitle(), 0);
sumy.put(emp.getJobTitle(), suma + emp.getSalary());
int ile = ilosci.getOrDefault(emp.getJobTitle(), 0);
ilosci.put(emp.getJobTitle(), ile + 1);
}
for(String job : sumy.keySet()) {
int ile = ilosci.get(job);
int suma = sumy.get(job);
double srednia = (double)suma / ile;
System.out.printf("%-32s | %2d | %8.2f\n", job, ile, srednia);
}
}
}
package emps;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Grupowanie4 {
// W wersjach 3-5 używamy nowych operacji słowników, które pojawiły się w Javie 8.
// putIfAbsent / computeIfPresent / compute - operacje, które działają w sposób warunkowy,
// a przekazuje do nich wartość lub funkcję służącą do zmiany wartości
// Ta wersja jest imo gorsza od 3 i 5...
// Pzy okazji używamy TreeMap - sortuje dane wg kluczy
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
Map<String, Integer> sumy = new TreeMap<>();
Map<String, Integer> ilosci = new TreeMap<>();
for(Employee emp : emps) {
sumy.putIfAbsent(emp.getJobTitle(), 0);
sumy.computeIfPresent(emp.getJobTitle(), (key, staraSuma) -> staraSuma + emp.getSalary());
ilosci.putIfAbsent(emp.getJobTitle(), 0);
ilosci.computeIfPresent(emp.getJobTitle(), (k, v) -> v+1);
}
for(String job : sumy.keySet()) {
int ile = ilosci.get(job);
int suma = sumy.get(job);
double srednia = (double)suma / ile;
System.out.printf("%-32s | %2d | %8.2f\n", job, ile, srednia);
}
}
}
package emps;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Grupowanie5 {
// W wersjach 3-5 używamy nowych operacji słowników, które pojawiły się w Javie 8.
// Tutaj operacja merge
// slownik.merge(KLUCZ, WARTOŚĆ, FUNKCJA)
// Jeśli pod KLUCZem jeszcze niczego nie ma, to wpisywana jest WARTOŚĆ
// Jeśli pod KLUCZem jest już STARA_WARTOŚĆ, to uruchamiana jest FUNKCJA
// NOWA_WARTOŚĆ := FUNKCJA(STARA_WARTOŚĆ, WARTOŚĆ)
// np. jeśli funkcją jest operacja dodawania, to będzie tak:
// NOWA_WARTOŚĆ := STARA_WARTOŚĆ + WARTOŚĆ
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
Map<String, Integer> sumy = new TreeMap<>();
Map<String, Integer> ilosci = new TreeMap<>();
for(Employee emp : emps) {
sumy.merge(emp.getJobTitle(), emp.getSalary(), Integer::sum);
ilosci.merge(emp.getJobTitle(), 1, Integer::sum);
// Funkcję aktualizującą można podać w formie wyrażenia lambda:
// sumy.merge(emp.getJobTitle(), emp.getSalary(), (stare, nowe) -> stare+nowe);
// ale dla dodawania mamy gotową operację Integer.sum(nowe, stare)
// i zamiast lambdy używamy referencji do metody (::)
}
for(String job : sumy.keySet()) {
int ile = ilosci.get(job);
int suma = sumy.get(job);
double srednia = (double)suma / ile;
System.out.printf("%-32s | %2d | %8.2f\n", job, ile, srednia);
}
}
}
package emps;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
public class Grupowanie6 {
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
Map<String, int[]> slownik = new TreeMap<>();
for(Employee emp : emps) {
if(slownik.containsKey(emp.getJobTitle())) {
// to jest kolejny pracownik z tego stanowiska → zwiększamy wartość w słowniku
int[] t = slownik.get(emp.getJobTitle());
t[0]++;
t[1] += emp.getSalary();
// dostaliśmy referencję do tablicy i gdy ją modyfikujemy, to słownik też to "widzi"
} else {
// to jest pierwszy pracownik z tego stanowiska → wpisujemy jego pensję jako wartość początkową
slownik.put(emp.getJobTitle(), new int[] {1, emp.getSalary()});
}
}
// przeglądamy "wpisy" w słowniku, czyli klucze wraz z wartościami
for (Entry<String, int[]> entry : slownik.entrySet()) {
String job = entry.getKey();
int[] t = entry.getValue();
double srednia = (double)t[1] / t[0];
System.out.printf("%-32s | %2d | %8.2f\n", job, t[0], srednia);
}
}
}
package emps;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
// Podejście obiektowe do grupowania.
public class Grupowanie7 {
public static void main(String[] args) {
final List<Employee> emps = ObslugaCSV.wczytaj();
final Map<String, JobInfo> mapa = new TreeMap<>();
for (Employee emp : emps) {
final String jobTitle = emp.getJobTitle();
JobInfo jobInfo = mapa.get(jobTitle);
if (jobInfo == null) {
jobInfo = new JobInfo(jobTitle);
mapa.put(jobTitle, jobInfo);
}
jobInfo.update(emp);
}
for (JobInfo jobInfo : mapa.values()) {
System.out.println(jobInfo);
}
}
// Klasa zgnieżdżona - tylko dla przykładu.
// Równie dobrze mógłbym tę klase zdefiniować w osobnym pliku.
// Obiekt tej klasy przechowuje statystyki job
private static class JobInfo {
final String jobTitle;
int count = 0;
int sum = 0;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
JobInfo(String jobTitle) {
this.jobTitle = jobTitle;
}
void update(Employee emp) {
int salary = emp.getSalary();
count++;
sum += salary;
if(salary < min) {
min = salary;
}
if(salary > max) {
max = salary;
}
}
double avg() {
return (double)sum / count;
}
@Override
public String toString() {
return "jobTitle=" + jobTitle + ", count=" + count + ", sum=" + sum + ", min=" + min + ", max="
+ max + ", avg=" + avg();
}
}
}
package emps;
import java.util.List;
public class Grupowanie_Switch {
// Ta wersja tylko jako wprowadzenie do wersji ze słownikami.
// Gdybyśmy dla każdego joba mieli oddzielną zmienną do liczenia sumy,
// moglibyśmy wszystko policzyć w jednej pętli.
// Problem:
// 1) program powinien czytać dowolne dane; nie powinien z góry zakładać, jakie są joby
// 2) każdy nowy job zwiększa ilość kodu.
// → jesli zamiast oddzielnych zmiennych użyjemy jednego słownika, to zrobimy to samo, ale zwięźlej
// słownik (Map) z kluczami typu String może być traktowany jako namiasta zestawu zmiennych,
// który możemy łatwo rozszerzać gdy pojawiają się nowe wartości
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj();
double sumaProgrammer = 0;
double sumaAccountant = 0;
double sumaPresident = 0;
// itd....
for (Employee emp : emps) {
switch(emp.getJobTitle()) {
case "Programmer" -> sumaProgrammer += emp.getSalary();
case "Accountant" -> sumaAccountant += emp.getSalary();
case "President" -> sumaPresident += emp.getSalary();
}
}
System.out.println(sumaProgrammer);
System.out.println(sumaAccountant);
System.out.println(sumaPresident);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment