Commit 6dd95496 by Patryk Czarnik

Gotowe przykłady

parent 442b2d06
package emps;
import java.util.List;
public class F9_Kwantyfikatory {
public static void main(String[] args) {
List<Employee> emps = ObslugaCSV.wczytaj("emps.csv");
// czy istnieje pracownik zarabiający 10 tys?
if(emps.stream().anyMatch(emp -> emp.getSalary() == 10_000)) {
System.out.println("A istnieje");
} else {
System.out.println("A nie istnieje");
}
// czy wszyscy pracownicy zarabiają co najmniej 3 tys?
if(emps.stream().allMatch(emp -> emp.getSalary() >= 3000)) {
System.out.println("B prawda");
} else {
System.out.println("B nieprawda");
}
// czy wszyscy programiści zarabiają co namjniej 3 tys?
boolean b3 = emps.stream()
.filter(emp -> "Programmer".equals(emp.getJobTitle()))
.allMatch(emp -> emp.getSalary() >= 3000);
if(b3) {
System.out.println("C prawda");
} else {
System.out.println("C nieprawda");
}
}
}
package p10_metody_klasy_object.finalizacja;
public class Konto {
final int numer;
int saldo;
Osoba wlasciciel;
public Konto(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer;
this.saldo = saldo;
this.wlasciciel = wlasciciel;
}
@Override
public String toString() {
return "Konto nr " + numer + ", " + saldo + ", wł." + wlasciciel;
}
void wplata(int kwota) {
saldo += kwota;
}
void wyplata(int kwota) {
saldo -= kwota;
}
static void przelew(Konto nadawca, Konto odbiorca, int kwota) {
nadawca.saldo -= kwota;
odbiorca.saldo += kwota;
}
void przelew(Konto odbiorca, int kwota) {
this.saldo -= kwota;
odbiorca.saldo += kwota;
}
@Override
protected void finalize() {
// to co tu wpiszemy, zostanie uruchomione tuż przed usunięciem obiektu przez GC
System.out.println("finalize Konto nr " + numer);
}
}
package p10_metody_klasy_object.finalizacja;
import java.time.LocalDate;
import java.time.Period;
public class Osoba {
// zmienne przechowywane w obiektach: pola (field), atrybuty (attribute), zmienne instancyjne (instance variable)
String imie, nazwisko;
LocalDate dataUrodzenia;
Osoba() {
}
Osoba(String imie, String nazwisko, LocalDate data) {
this.imie = imie;
this.nazwisko = nazwisko;
dataUrodzenia = data;
}
Osoba(String imie, String nazwisko, String data) {
this(imie, nazwisko, LocalDate.parse(data));
}
// metody - operacje, które "potrafi" wykonać obiekt
void przedstawSie() {
System.out.println("Nazywam się " + imie + " " + nazwisko + " i mam " + getWiek() + " lat.");
}
public String toString() {
return imie + " " + nazwisko + " ur." + dataUrodzenia;
}
public int getWiek() {
if(dataUrodzenia == null) {
return -1;
}
Period czasZycia = Period.between(dataUrodzenia, LocalDate.now());
return czasZycia.getYears();
}
@Override
protected void finalize() {
System.out.println("finalize Osoba " + imie);
}
}
package p10_metody_klasy_object.finalizacja;
public class Usuwanie1 {
public static void main(String[] args) {
System.out.println("Tworzymy dużo obiektów");
Osoba osoba = new Osoba("Ala", "Kowalska", "1993-04-05");
for(int i = 0; i < 100; i++) {
Konto k = new Konto(i, 1000+i, osoba);
// od tego miejsca już z tego Konta nie korzystam
}
osoba = null;
System.out.println("Gotowe...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// nie zobaczymy finalize
System.out.println("Koniec programu");
}
}
package p10_metody_klasy_object.finalizacja;
public class Usuwanie2_OutOfMemory {
public static void main(String[] args) {
System.out.println("Tworzymy dużo obiektów");
Osoba osoba = new Osoba("Ala", "Kowalska", "1993-04-05");
for(int i = 0; i < 100; i++) {
Konto k = new Konto(i, 1000+i, osoba);
// od tego miejsca już z tego Konta nie korzystam
}
osoba = null;
System.out.println("Gotowe...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("Alokuję dużą tablicę");
try {
long[] t = new long[1000_000_000]; // 8G pamięci
System.out.println("mam tablicę");
} catch (OutOfMemoryError e) {
System.err.println("brak pamięci");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("Koniec programu");
}
}
package p10_metody_klasy_object.finalizacja;
public class Usuwanie3_gc {
public static void main(String[] args) {
System.out.println("Tworzymy dużo obiektów");
for(int i = 0; i < 100; i++) {
Konto k = new Konto(i, 1000+i, null);
// od tego miejsca już z tego Konta nie korzystam
}
System.out.println("Gotowe...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("Wywołuję System.gc()");
System.gc();
System.out.println("wywołałem");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("Koniec programu");
}
}
package p10_metody_klasy_object.finalizacja;
import java.util.LinkedList;
import java.util.List;
public class Usuwanie4_Lista {
public static void main(String[] args) {
Osoba osoba = new Osoba("Ala", "Kowalska", "1993-04-05");
List<Konto> lista = new LinkedList<>();
for(int i = 1; i <= 100; i++) {
Konto k = new Konto(i, 100*i, osoba);
lista.add(k);
}
System.out.println("Konta utworzone");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
osoba = null;
System.out.println("Odpalam GC");
System.gc();
System.out.println("GC odpalone");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(lista.get(50));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
System.out.println("Zapominam o liście i ponownie robię GC");
lista = null;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.gc();
System.out.println("GC odpalone");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("koniec");
}
}
package p10_metody_klasy_object.finalizacja;
import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;
public class Usuwanie5_Weak {
public static void main(String[] args) {
Osoba osoba = new Osoba("Ala", "Kowalska", "1993-04-05");
List<WeakReference<Konto>> lista = new LinkedList<>();
for(int i = 1; i <= 100; i++) {
Konto k = new Konto(i, 100*i, osoba);
lista.add(new WeakReference<Konto>(k));
}
System.out.println("Konta utworzone");
System.out.println("przykładowe konto: " + lista.get(50).get());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
osoba = null;
System.out.println("Odpalam GC");
System.gc();
System.out.println("GC odpalone\n");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("teraz odczyt konta: " + lista.get(50).get());
System.out.println("koniec");
}
}
package p10_metody_klasy_object.klonowanie1;
public class Konto implements Cloneable {
final int numer;
int saldo;
Osoba wlasciciel;
public Konto(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer;
this.saldo = saldo;
this.wlasciciel = wlasciciel;
}
@Override
public String toString() {
return "Konto nr " + numer + ", " + saldo + ", wł." + wlasciciel;
}
void wplata(int kwota) {
saldo += kwota;
}
void wyplata(int kwota) {
saldo -= kwota;
}
static void przelew(Konto nadawca, Konto odbiorca, int kwota) {
nadawca.saldo -= kwota;
odbiorca.saldo += kwota;
}
void przelew(Konto odbiorca, int kwota) {
this.saldo -= kwota;
odbiorca.saldo += kwota;
}
/* W tej wersji korzystam z domyślnej implementacji clone(), tylko ją upubliczniam.
*/
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
package p10_metody_klasy_object.klonowanie1;
import java.time.LocalDate;
import java.time.Period;
public class Osoba implements Cloneable {
// zmienne przechowywane w obiektach: pola (field), atrybuty (attribute), zmienne instancyjne (instance variable)
String imie, nazwisko;
LocalDate dataUrodzenia;
Osoba() {
}
Osoba(String imie, String nazwisko, LocalDate data) {
this.imie = imie;
this.nazwisko = nazwisko;
dataUrodzenia = data;
}
Osoba(String imie, String nazwisko, String data) {
this(imie, nazwisko, LocalDate.parse(data));
}
// metody - operacje, które "potrafi" wykonać obiekt
void przedstawSie() {
System.out.println("Nazywam się " + imie + " " + nazwisko + " i mam " + getWiek() + " lat.");
}
public String toString() {
return imie + " " + nazwisko + " ur." + dataUrodzenia;
}
public int getWiek() {
if(dataUrodzenia == null) {
return -1;
}
Period czasZycia = Period.between(dataUrodzenia, LocalDate.now());
return czasZycia.getYears();
}
@Override
public Osoba clone() {
try {
return (Osoba) super.clone();
} catch (CloneNotSupportedException e) {
// should never happen
throw new RuntimeException(e);
}
}
}
package p10_metody_klasy_object.klonowanie1;
public class TestKlonowania {
public static void main(String[] args) {
// Użycie domyślnej wersji clone wymaga rzutowania obiektu na właściwy typ i obsłużenia wyjątku CloneNotSupportedException
try {
Osoba ala = new Osoba("Ala", "Kowalska", "2001-02-03");
Konto konto = new Konto(1, 1000, ala);
Konto klon;
klon = (Konto) konto.clone();
System.out.println("oryginał: " + konto);
System.out.println("klon : " + klon);
System.out.println();
klon.wplata(300);
klon.wlasciciel.imie = "Alicja";
System.out.println("oryginał: " + konto);
System.out.println("klon : " + klon);
System.out.println();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
package p10_metody_klasy_object.klonowanie2;
public class Konto implements Cloneable {
final int numer;
int saldo;
Osoba wlasciciel;
public Konto(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer;
this.saldo = saldo;
this.wlasciciel = wlasciciel;
}
@Override
public String toString() {
return "Konto nr " + numer + ", " + saldo + ", wł." + wlasciciel;
}
void wplata(int kwota) {
saldo += kwota;
}
void wyplata(int kwota) {
saldo -= kwota;
}
static void przelew(Konto nadawca, Konto odbiorca, int kwota) {
nadawca.saldo -= kwota;
odbiorca.saldo += kwota;
}
void przelew(Konto odbiorca, int kwota) {
this.saldo -= kwota;
odbiorca.saldo += kwota;
}
/* W tej wersji korzystam z domyślnej implementacji clone()
* upubliczniając ją i dostosowując do łatwiego używania (zmiana typu, bez deklarowanego wyjątku).
* Domyślnie tworzy to płytką kopię.
* Wg mnie wygląda to paskudnie.
*/
@Override
public Konto clone() {
try {
return (Konto)super.clone();
} catch (CloneNotSupportedException e) {
// should never happen
throw new RuntimeException(e);
}
}
}
package p10_metody_klasy_object.klonowanie2;
import java.time.LocalDate;
import java.time.Period;
public class Osoba implements Cloneable {
// zmienne przechowywane w obiektach: pola (field), atrybuty (attribute), zmienne instancyjne (instance variable)
String imie, nazwisko;
LocalDate dataUrodzenia;
Osoba() {
}
Osoba(String imie, String nazwisko, LocalDate data) {
this.imie = imie;
this.nazwisko = nazwisko;
dataUrodzenia = data;
}
Osoba(String imie, String nazwisko, String data) {
this(imie, nazwisko, LocalDate.parse(data));
}
// metody - operacje, które "potrafi" wykonać obiekt
void przedstawSie() {
System.out.println("Nazywam się " + imie + " " + nazwisko + " i mam " + getWiek() + " lat.");
}
public String toString() {
return imie + " " + nazwisko + " ur." + dataUrodzenia;
}
public int getWiek() {
if(dataUrodzenia == null) {
return -1;
}
Period czasZycia = Period.between(dataUrodzenia, LocalDate.now());
return czasZycia.getYears();
}
@Override
public Osoba clone() {
try {
return (Osoba) super.clone();
} catch (CloneNotSupportedException e) {
// should never happen
throw new RuntimeException(e);
}
}
}
package p10_metody_klasy_object.klonowanie2;
public class TestKlonowania {
public static void main(String[] args) {
Osoba ala = new Osoba("Ala", "Kowalska", "2001-02-03");
Konto konto = new Konto(1, 1000, ala);
Konto klon = konto.clone();
System.out.println("oryginał: " + konto);
System.out.println("klon : " + klon);
System.out.println();
klon.wplata(300);
klon.wlasciciel.imie = "Alicja";
System.out.println("oryginał: " + konto);
System.out.println("klon : " + klon);
System.out.println();
}
}
package p10_metody_klasy_object.klonowanie3;
public class Konto implements Cloneable {
final int numer;
int saldo;
Osoba wlasciciel;
public Konto(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer;
this.saldo = saldo;
this.wlasciciel = wlasciciel;
}
@Override
public String toString() {
return "Konto nr " + numer + ", " + saldo + ", wł." + wlasciciel;
}
void wplata(int kwota) {
saldo += kwota;
}
void wyplata(int kwota) {
saldo -= kwota;
}
static void przelew(Konto nadawca, Konto odbiorca, int kwota) {
nadawca.saldo -= kwota;
odbiorca.saldo += kwota;
}
void przelew(Konto odbiorca, int kwota) {
this.saldo -= kwota;
odbiorca.saldo += kwota;
}
/* W tej wersji korzystam z domyślnej implementacji clone()
* upubliczniając ją i dostosowując do łatwiego używania (zmiana typu, bez deklarowanego wyjątku).
* Ponadto staram się, aby clone() tworzył głęboką kopię - zmieniam pole wlasciciel.
* Nie ma natomiast potrzeby klonować pól, które są klas niemutowalnych (String, LocalDate itp.).
*/
@Override
public Konto clone() {
try {
Konto klon = (Konto) super.clone();
klon.wlasciciel = wlasciciel.clone();
return klon;
} catch (CloneNotSupportedException e) {
// should never happen
throw new RuntimeException(e);
}
}
}
package p10_metody_klasy_object.klonowanie3;
import java.time.LocalDate;
import java.time.Period;
public class Osoba implements Cloneable {
// zmienne przechowywane w obiektach: pola (field), atrybuty (attribute), zmienne instancyjne (instance variable)
String imie, nazwisko;
LocalDate dataUrodzenia;
Osoba() {
}
Osoba(String imie, String nazwisko, LocalDate data) {
this.imie = imie;
this.nazwisko = nazwisko;
dataUrodzenia = data;
}
Osoba(String imie, String nazwisko, String data) {
this(imie, nazwisko, LocalDate.parse(data));
}
// metody - operacje, które "potrafi" wykonać obiekt
void przedstawSie() {
System.out.println("Nazywam się " + imie + " " + nazwisko + " i mam " + getWiek() + " lat.");
}
public String toString() {
return imie + " " + nazwisko + " ur." + dataUrodzenia;
}
public int getWiek() {
if(dataUrodzenia == null) {
return -1;
}
Period czasZycia = Period.between(dataUrodzenia, LocalDate.now());
return czasZycia.getYears();
}
@Override
public Osoba clone() {
try {
return (Osoba) super.clone();
} catch (CloneNotSupportedException e) {
// should never happen
throw new RuntimeException(e);
}
}
}
package p10_metody_klasy_object.klonowanie3;
public class TestKlonowania {
public static void main(String[] args) {
Osoba ala = new Osoba("Ala", "Kowalska", "2001-02-03");
Konto konto = new Konto(1, 1000, ala);
Konto klon = konto.clone();
System.out.println("oryginał: " + konto);
System.out.println("klon : " + klon);
System.out.println();
klon.wplata(300);
klon.wlasciciel.imie = "Alicja";
System.out.println("oryginał: " + konto);
System.out.println("klon : " + klon);
System.out.println();
}
}
package p10_metody_klasy_object.klonowanie4;
public class Konto implements Cloneable {
final int numer;
int saldo;
Osoba wlasciciel;
public Konto(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer;
this.saldo = saldo;
this.wlasciciel = wlasciciel;
}
@Override
public String toString() {
return "Konto nr " + numer + ", " + saldo + ", wł." + wlasciciel;
}
void wplata(int kwota) {
saldo += kwota;
}
void wyplata(int kwota) {
saldo -= kwota;
}
static void przelew(Konto nadawca, Konto odbiorca, int kwota) {
nadawca.saldo -= kwota;
odbiorca.saldo += kwota;
}
void przelew(Konto odbiorca, int kwota) {
this.saldo -= kwota;
odbiorca.saldo += kwota;
}
/* W tej wersji tworzę własną implementację clone() za pomocą konstruktora.
* Wg mnie wygląda to znacznie lepiej.
* W tej wersji od razu głęboka kopia.
*/
@Override
public Konto clone() {
return new Konto(this.numer, this.saldo, this.wlasciciel.clone());
}
}
package p10_metody_klasy_object.klonowanie4;
import java.time.LocalDate;
import java.time.Period;
public class Osoba implements Cloneable {
// zmienne przechowywane w obiektach: pola (field), atrybuty (attribute), zmienne instancyjne (instance variable)
String imie, nazwisko;
LocalDate dataUrodzenia;
Osoba() {
}
Osoba(String imie, String nazwisko, LocalDate data) {
this.imie = imie;
this.nazwisko = nazwisko;
dataUrodzenia = data;
}
Osoba(String imie, String nazwisko, String data) {
this(imie, nazwisko, LocalDate.parse(data));
}
// metody - operacje, które "potrafi" wykonać obiekt
void przedstawSie() {
System.out.println("Nazywam się " + imie + " " + nazwisko + " i mam " + getWiek() + " lat.");
}
public String toString() {
return imie + " " + nazwisko + " ur." + dataUrodzenia;
}
public int getWiek() {
if(dataUrodzenia == null) {
return -1;
}
Period czasZycia = Period.between(dataUrodzenia, LocalDate.now());
return czasZycia.getYears();
}
@Override
protected Osoba clone() {
return new Osoba(imie, nazwisko, dataUrodzenia);
// String i LocalDate nie trzeba już klonować, ponieważ są to klasy immutable
}
}
package p10_metody_klasy_object.klonowanie4;
public class TestKlonowania {
public static void main(String[] args) {
Osoba ala = new Osoba("Ala", "Kowalska", "2001-02-03");
Konto konto = new Konto(1, 1000, ala);
Konto klon = konto.clone();
System.out.println("oryginał: " + konto);
System.out.println("klon : " + klon);
System.out.println();
klon.wplata(300);
klon.wlasciciel.imie = "Alicja";
System.out.println("oryginał: " + konto);
System.out.println("klon : " + klon);
System.out.println();
}
}
package p10_metody_klasy_object.porownywanie;
class A {
int x, y;
public A(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "( " + x + "," + y +")";
}
}
public class Porownywanie1 {
public static void main(String[] args) {
A a1 = new A(10, 20);
A a2 = new A(10, 20);
A a3 = new A(10, 30);
System.out.println(a1 == a2);
System.out.println(a1 == a3);
System.out.println();
System.out.println(a1.equals(a2));
System.out.println(a1.equals(a3));
}
}
package p10_metody_klasy_object.porownywanie;
import java.util.HashSet;
// Ta wersja nie nadpisuje equals! Tylko dodaje inną metodę
class B {
int x, y;
public B(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "(" + x + "," + y +")";
}
public boolean equals(B that) {
return this.x == that.x && this.y == that.y;
}
public int hashCode() {
return 0;
}
}
public class Porownywanie2 {
public static void main(String[] args) {
B b1 = new B(10, 20);
B b2 = new B(10, 20);
B b3 = new B(10, 30);
System.out.println(b1.toString());
System.out.println(b2.toString());
System.out.println(b3.toString());
System.out.println(b1 == b2);
System.out.println(b1 == b3);
System.out.println();
// chociaż nieprawidłowo zaimplementowałem equals w klasie B, to ten test działa
System.out.println(b1.equals(b2));
System.out.println(b1.equals(b3));
System.out.println();
Object o1 = b1;
Object o2 = b2;
Object o3 = b3;
System.out.println(o1.equals(o2)); // tu działa wersja z Object
System.out.println(o1.equals(o3));
System.out.println();
HashSet<B> zbior = new HashSet<>();
zbior.add(b1);
zbior.add(b2);
zbior.add(b3);
System.out.println(zbior.size());
System.out.println(zbior);
}
}
package p10_metody_klasy_object.porownywanie;
import java.util.HashSet;
class C {
int x, y;
public C(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "(" + x + "," + y +")";
}
@Override
public boolean equals(Object o) {
if(o instanceof C) {
C that = (C)o;
return this.x == that.x && this.y == that.y;
} else {
return false;
}
}
@Override
public int hashCode() {
// taki hashCode jest poprawny, w tym sensie, że spełnia minimalne wymagania kontraktu
// zazwyczaj taka implementacja jest niewydajna i w praktyce tak się nie robi
return 0;
}
}
public class Porownywanie3 {
public static void main(String[] args) {
C c1 = new C(10, 20);
C c2 = new C(10, 20);
C c3 = new C(10, 30);
System.out.println(c1.toString());
System.out.println(c2.toString());
System.out.println(c3.toString());
System.out.println(c1 == c2);
System.out.println(c1 == c3);
System.out.println();
// chociaż nieprawidłowo zaimplementowałem equals w klasie B, to ten test działa
System.out.println(c1.equals(c2));
System.out.println(c1.equals(c3));
System.out.println();
Object o1 = c1;
Object o2 = c2;
Object o3 = c3;
System.out.println(o1.equals(o2)); // tu działa wersja z Object
System.out.println(o1.equals(o3));
System.out.println();
HashSet<C> zbior = new HashSet<>();
zbior.add(c1);
zbior.add(c2);
zbior.add(c3);
System.out.println(zbior.size());
System.out.println(zbior);
}
}
package p10_metody_klasy_object.porownywanie;
import java.util.HashSet;
class D {
int x, y;
public D(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "(" + x + "," + y +")";
}
@Override
public boolean equals(Object o) {
if(o instanceof D) {
D that = (D)o;
return this.x == that.x && this.y == that.y;
} else {
return false;
}
}
@Override
public int hashCode() {
// poprawnym hashCode będzie każdy, który do uzyskania wyniku używa wyłącznie wartości porównywanych w equals
return x*y;
}
}
public class Porownywanie4 {
public static void main(String[] args) {
D d1 = new D(10, 20);
D d2 = new D(10, 20);
D d3 = new D(10, 30);
System.out.println(d1.toString());
System.out.println(d2.toString());
System.out.println(d3.toString());
System.out.println(d1 == d2);
System.out.println(d1 == d3);
System.out.println();
// chociaż nieprawidłowo zaimplementowałem equals w klasie B, to ten test działa
System.out.println(d1.equals(d2));
System.out.println(d1.equals(d3));
System.out.println();
Object o1 = d1;
Object o2 = d2;
Object o3 = d3;
System.out.println(o1.equals(o2)); // tu działa wersja z Object
System.out.println(o1.equals(o3));
System.out.println();
HashSet<D> zbior = new HashSet<>();
zbior.add(d1);
zbior.add(d2);
zbior.add(d3);
System.out.println(zbior.size());
System.out.println(zbior);
}
}
package p13_lambdy.v1;
public interface FunkcjaLiczbowa {
double oblicz(double arg);
}
package p13_lambdy.v1;
public class Lambdy1 {
public static void main(String[] args) {
FunkcjaLiczbowa f1 = (double arg) -> {
System.out.println("liczę i liczę...");
return arg + 100;
};
System.out.println(f1.oblicz(13));
System.out.println(f1.oblicz(77));
System.out.println();
FunkcjaLiczbowa f2 = x -> x*x;
System.out.println(f2.oblicz(5.0));
System.out.println(f2.oblicz(12.5));
// Oprócz wyrażeń lambda, funkcje można wskazywać także za pomocą "method reference"
FunkcjaLiczbowa f3 = Math::sqrt;
System.out.println(f3.oblicz(36));
FunkcjaLiczbowa f4 = x -> Math.sqrt(x);
System.out.println(f4.oblicz(36));
System.out.println();
}
}
package p13_lambdy.v1;
public class Lambdy2 {
public static void main(String[] args) {
FunkcjaLiczbowa f2 = x -> x*x;
System.out.println(f2.oblicz(5.0));
System.out.println(f2.oblicz(12.5));
// Technicznie: w f1 i f2 są wpisane OBIEKTY
Object o = f2;
System.out.println(o);
// Są to obiekty klas generowanych automatycznie,
// te klasy implementują interfejs FunkcjaLiczbowa.
System.out.println(f2.getClass());
if(f2 instanceof FunkcjaLiczbowa) {
System.out.println("Jest instancją");
} else {
System.out.println("Nie jest instancją");
}
// Podczas kompilacji z kontekstu musi wynikać do jakiego interfejsu ma być dopasowana dana lambda.
// Object o2 = x -> 100*x + 13;
// Object o3 = (double x) -> {return 100*x + 13;};
}
}
package p13_lambdy.v1;
public class TradycyjneUzycieInterfejsu {
public static void main(String[] args) {
ZwyklaImplementacja f1 = new ZwyklaImplementacja();
System.out.println( f1.oblicz(1.0) );
System.out.println( f1.oblicz(1.5) );
// obiekt klasy implementującej interfejs mogę zapisać na zmienną typu interfejs
FunkcjaLiczbowa f2 = new ZwyklaImplementacja();
System.out.println( f2.oblicz(2.0) );
// Przed Javą 8 najbardziej zwięzłym sposobem na utworzenie obiektu zgodnego z interfejsem
// była "klasa anonimowa":
FunkcjaLiczbowa f3 = new FunkcjaLiczbowa() {
public double oblicz(double x) {
return x*x*x;
}
};
System.out.println( f3.oblicz(3.0) );
}
}
package p13_lambdy.v1;
public class ZwyklaImplementacja implements FunkcjaLiczbowa {
@Override
public double oblicz(double arg) {
return arg*arg;
}
}
package p13_lambdy.v2;
@FunctionalInterface
public interface FunkcjaLiczbowa {
double oblicz(double arg);
default String nazwa() {
return "moja funkcja";
}
}
package p13_lambdy.v2;
public class Lambdy1 {
public static void main(String[] args) {
FunkcjaLiczbowa f1 = (double arg) -> {
System.out.println("liczę i liczę...");
return arg + 100;
};
System.out.println(f1.oblicz(13));
System.out.println(f1.oblicz(77));
System.out.println();
FunkcjaLiczbowa f2 = x -> x*x;
System.out.println(f2.oblicz(5.0));
System.out.println(f2.oblicz(12.5));
// Oprócz wyrażeń lambda, funkcje można wskazywać także za pomocą "method reference"
FunkcjaLiczbowa f3 = Math::sqrt;
System.out.println(f3.oblicz(36));
FunkcjaLiczbowa f4 = x -> Math.sqrt(x);
System.out.println(f4.oblicz(36));
System.out.println();
}
}
package p13_lambdy.v2;
public class Lambdy2 {
public static void main(String[] args) {
FunkcjaLiczbowa f2 = x -> x*x;
System.out.println(f2.oblicz(5.0));
System.out.println(f2.oblicz(12.5));
// Technicznie: w f1 i f2 są wpisane OBIEKTY
Object o = f2;
System.out.println(o);
// Są to obiekty klas generowanych automatycznie,
// te klasy implementują interfejs FunkcjaLiczbowa.
System.out.println(f2.getClass());
if(f2 instanceof FunkcjaLiczbowa) {
System.out.println("Jest instancją");
} else {
System.out.println("Nie jest instancją");
}
// Podczas kompilacji z kontekstu musi wynikać do jakiego interfejsu ma być dopasowana dana lambda.
// Object o2 = x -> 100*x + 13;
// Object o3 = (double x) -> {return 100*x + 13;};
}
}
package p13_lambdy.v2;
public class MojFrameworkFunkcyjny {
public static void zamien(double[] tablica, FunkcjaLiczbowa f) {
for (int i = 0; i < tablica.length; i++) {
tablica[i] = f.oblicz(tablica[i]);
}
}
}
package p13_lambdy.v2;
public class TradycyjneUzycieInterfejsu {
public static void main(String[] args) {
ZwyklaImplementacja f1 = new ZwyklaImplementacja();
System.out.println( f1.oblicz(1.0) );
System.out.println( f1.oblicz(1.5) );
// obiekt klasy implementującej interfejs mogę zapisać na zmienną typu interfejs
FunkcjaLiczbowa f2 = new ZwyklaImplementacja();
System.out.println( f2.oblicz(2.0) );
// Przed Javą 8 najbardziej zwięzłym sposobem na utworzenie obiektu zgodnego z interfejsem
// była "klasa anonimowa":
FunkcjaLiczbowa f3 = new FunkcjaLiczbowa() {
public double oblicz(double x) {
return x*x*x;
}
};
System.out.println( f3.oblicz(3.0) );
}
}
package p13_lambdy.v2;
import java.util.Arrays;
public class UzycieFramworku {
public static void main(String[] args) {
double[] a = { 0, 10, 20, 30, 40, 50 };
double[] b = { 100, 16, 25, 2 };
System.out.println("a: " + Arrays.toString(a));
System.out.println("b: " + Arrays.toString(b));
System.out.println();
MojFrameworkFunkcyjny.zamien(a, x -> x*x);
System.out.println("a: " + Arrays.toString(a));
MojFrameworkFunkcyjny.zamien(a, x -> x+5);
System.out.println("a: " + Arrays.toString(a));
MojFrameworkFunkcyjny.zamien(b, Math::sqrt);
System.out.println("b: " + Arrays.toString(b));
}
}
package p13_lambdy.v2;
public class ZwyklaImplementacja implements FunkcjaLiczbowa {
@Override
public double oblicz(double arg) {
return arg*arg;
}
}
package p13_lambdy.v3;
public class DoKwadratu implements FunkcjaLiczbowa {
@Override
public double oblicz(double x) {
return x * x;
}
}
package p13_lambdy.v3;
import java.util.ArrayList;
import java.util.List;
public class EffectivelyFinal {
private static int statyczna = 0;
public static void main(String[] args) {
// W wyrażeniach lambda (podobnie jak w klasach anonimowych) nie można używać zmiennych lokalnych, które są modyfikowane
// Przykład kiedy to przeszkadza w praktyce:
List<String> imiona = new ArrayList<>();
imiona.add("Ala");
imiona.add("Aleksandra");
imiona.add("Ula");
imiona.add("Elżbieta");
double liczba = 0;
liczba = liczba + imiona.size();
int x = 0;
// Głupie rozwiązanie problemu "ile jest jest imion 3-literowych"
imiona.forEach(s -> {
if(s.length() == 3) {
//NK x++; // wewnątrz wyrażeń lambda nie można modyfikować zmiennych lokalnych z otoczenia
// ani nawet używać zmiennych modyfikowanych poza lambdą
//NK System.out.println(liczba);
// mamy dostęp do zmiennych z poziomu klasy (statycznych, isntancyjnych)
statyczna++;
// ale to zły styl
}
});
System.out.println(" x : " + x);
System.out.println("statyczna : " + statyczna);
}
}
package p13_lambdy.v3;
@FunctionalInterface
public interface FunkcjaLiczbowa {
// interfejs funkcyjny może zawierać metody defaultowe i statyczne
// ale ma zawierać dokładnie jedną metodę abstrakcyjną (czyli niezaimplementowaną)
double oblicz(double arg);
// aplikuje bieżącą funkcję podwójnie
default double podwojnie(double arg) {
return oblicz(oblicz(arg));
}
default FunkcjaLiczbowa zloz(FunkcjaLiczbowa nastepnyKrok) {
return x -> {
double wynikPosredni = oblicz(x);
double wynikKoncowy = nastepnyKrok.oblicz(wynikPosredni);
return wynikKoncowy;
};
}
static FunkcjaLiczbowa identycznosc() {
return x -> x;
}
}
package p13_lambdy.v3;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.UnaryOperator;
public class ReferencjeDoMetod {
public static void main(String[] args) {
List<String> lista = new ArrayList<>();
lista.add("Ala");
lista.add("Ola");
lista.add("Ela");
// Jeśli istnieje metoda, której chcemy użyć, to zamiast pisać taką trywialną lambdę
FunkcjaLiczbowa f1 = x -> Klasa.aaa(x);
System.out.println(f1.oblicz(10));
// możemy bezpośrednio wskazać tę metodę
// Opcja 1: wskazujemy metodę statyczną poprzez klasę
FunkcjaLiczbowa f2 = Klasa::aaa;
System.out.println(f2.oblicz(10));
System.out.println();
// Opcja 2: wskazujemy metodę instancyjną poprzez obiekt
Klasa obiekt = new Klasa(50);
FunkcjaLiczbowa f3 = obiekt::bbb;
System.out.println(f3.oblicz(10));
FunkcjaLiczbowa f4 = x -> obiekt.bbb(x);
System.out.println(f4.oblicz(10));
System.out.println();
// Opcja 3: wskazujemy metodę instancyjną poprzez klasę.
// Wówczas this jest traktowany jak pierwszy argument funkcji.
UnaryOperator<String> naDuzeLitery = String::toUpperCase;
System.out.println(naDuzeLitery.apply("Ala ma kota"));
System.out.println();
lista.stream()
.map(naDuzeLitery)
.forEach(System.out::print);
System.out.println();
lista.stream()
.map(String::toUpperCase)
.forEach(System.out::print);
System.out.println();
lista.stream()
.map(x -> x.toUpperCase())
.forEach(System.out::print);
System.out.println();
System.out.println();
Comparator<String> komp1 = (s1, s2) -> s1.compareTo(s2);
Comparator<String> komp2 = String::compareTo;
// jakby (this, argument) -> this.compareTo(argument);
lista.stream().sorted(String::compareTo).forEachOrdered(System.out::println);
}
static class Klasa {
private int wartosc;
public Klasa(int x) {
this.wartosc = x;
}
static double aaa(double x) {
return x+1;
}
double bbb(double x) {
return x+wartosc;
}
}
}
package p13_lambdy.v3;
import java.time.LocalTime;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntUnaryOperator;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
public class SkladniaLambd {
static int globalna = 0;
public static void main(String[] args) {
FunkcjaLiczbowa f1 = (double arg) -> {
System.out.println("obliczam...");
double z = arg * arg;
globalna++;
return z + 5;
};
System.out.println("a kuku");
double wynik = f1.oblicz(7);
System.out.println(wynik);
// pomijam typ argumentu
FunkcjaLiczbowa f2 = (arg) -> {return arg + 5;};
//FunkcjaLiczbowa f2 = (arg) -> return arg + 5;
// jeśli prawa strona sprowadza się do jednego return, można od razu pisać wynim bez klamerek i bez return:
FunkcjaLiczbowa f3 = (arg) -> arg + 5;
// tutaj średnik należy do instrukcji przypisania, a nie jest częścią lambdy
FunkcjaLiczbowa f3a = ( (arg) -> arg + 5 ) ;
// jeśli po lewej stronie jest jeden argument bez typu, to można pominąć nawiasy
FunkcjaLiczbowa f4 = arg -> arg + 5;
// Consumer jest typu T -> void czyli nie zwraca wyniku
Consumer<String> cs1 = s -> {System.out.println(s);};
// nawet jeśli metoda nie zwraca wyniku, ale jest zbudowana z jednego polecenia, można pominąć nawiasy klamrowe
Consumer<String> cs2 = s -> System.out.println(s) ;
Function<String, Integer> ff = s -> s.length();
UnaryOperator<String> un = s -> s.toUpperCase();
IntUnaryOperator iun = i -> 10*i;
int x = 15;
int y = -x; // minus jest "operatorem unarnym", stąd się wzięła nazwa dla funkcji przyjmujących jeden argument
// Jeśli parametrów jest więcej niż 1, to musimy wziąć je w nawiasy
// Albo podajemy typy wszystkich parametrów, albo żadnego
// Comparator<String> komp = x, y -> x.compareToIgnoreCase(y);
Comparator<String> komp1 = (String s1, String s2) -> s1.compareToIgnoreCase(s2);
Comparator<String> komp2 = (s1, s2) -> s1.compareToIgnoreCase(s2);
//NK Comparator<String> komp3 = (String s1, s2) -> s1.compareToIgnoreCase(s2);
// Jeśli metoda nie przyjmuje parametrów, to po lewej stronie strzałki piszemy puste nawiasy
Runnable r1 = () -> {};
Runnable r2 = () -> {System.out.println("Hello world");};
//NK Runnable r2a = (void) -> {System.out.println("Hello world");};
// nawet jeśli funkcja jest typu void (nie zwraca wyniku), a treść ogranicza się do jednej instrukcji,
// to tę instrukcję możemy napisać bez klamerek
Runnable r3 = () -> System.out.println("Hello world");
Runnable r4 = () -> globalna = 103;
System.out.println("gloalna przed: " + globalna);
r4.run();
System.out.println("gloalna przed: " + globalna);
Consumer<String> cs4 = napis -> System.out.println(napis.length());
Supplier<String> dajDate = () -> LocalTime.now().toString();
// nazwami parametrów w lambdach nie mogą być zajęte nazwy zmiennych lokalnych
// Comparator<String> komp2 = (x, y) -> x.compareToIgnoreCase(y);
System.out.println();
for(int i = 0; i < 10; i++)
System.out.println(dajDate.get());
}
}
package p13_lambdy.v3;
public class Test1 {
public static void main(String[] args) {
FunkcjaLiczbowa f1 = new DoKwadratu();
System.out.println(f1.oblicz(5.0));
FunkcjaLiczbowa f2 = new FunkcjaLiczbowa() {
public double oblicz(double x) {
return x*x;
}
};
System.out.println(f2.oblicz(5.0));
FunkcjaLiczbowa f3 = y -> y*y;
System.out.println(f3.oblicz(5.0));
FunkcjaLiczbowa f4 = Math::sqrt;
System.out.println(f4.oblicz(25.0));
}
}
package p13_lambdy.v3;
import java.util.function.DoubleUnaryOperator;
public class Test2 {
public static void main(String[] args) {
FunkcjaLiczbowa razy2 = x -> x*2;
FunkcjaLiczbowa razy10 = x -> x*10;
FunkcjaLiczbowa plus3 = x -> x+3;
FunkcjaLiczbowa kwadrat = x -> x*x;
FunkcjaLiczbowa pierwiastek = Math::sqrt;
System.out.println(razy2.oblicz(10));
FunkcjaLiczbowa zlozenie1 = razy10.zloz(plus3);
System.out.println(zlozenie1.oblicz(10));
FunkcjaLiczbowa zlozenie2 = kwadrat.zloz(pierwiastek);
System.out.println(zlozenie2.oblicz(10));
System.out.println(zlozenie2.oblicz(50));
System.out.println(zlozenie2.oblicz(5.5));
FunkcjaLiczbowa zlozenie3 = pierwiastek.zloz(kwadrat);
System.out.println(zlozenie3.oblicz(2));
FunkcjaLiczbowa zlozenie4 = pierwiastek.zloz(pierwiastek);
System.out.println(zlozenie4.oblicz(10000));
System.out.println(zlozenie4.oblicz(625));
FunkcjaLiczbowa ident = FunkcjaLiczbowa.identycznosc();
System.out.println(ident.oblicz(113)); // 113
System.out.println(kwadrat.podwojnie(3)); // 81
// Takie rzeczy naprawdę istnieją:
DoubleUnaryOperator f1 = Math::sqrt;
DoubleUnaryOperator f2 = y -> y*y;
DoubleUnaryOperator f3 = f1.andThen(f2);
System.out.println(f3.applyAsDouble(2));
System.out.println(f1.andThen(f1).applyAsDouble(625));
}
}
package p13_lambdy.v3;
import static p13_lambdy.v3.ZastosowaniaFunkcjiLiczbowej.*;
import java.util.Arrays;
// To już już jest kod pisany na co dzień przez zwykłych programistów,
// który używają gotowych schematów.
public class UzycieLambd2 {
public static void main(String[] args) {
double[] a = {0, 10, 20, 30, 40, 50};
double[] b = {100, 16, 25, 2};
System.out.println("a: " + Arrays.toString(a));
System.out.println("b: " + Arrays.toString(b));
System.out.println();
// tutaj mogę w wygodny sposób podawać funkcje
zastosujdoTablicy(a, x -> x*x);
zastosujdoTablicy(b, Math::sqrt);
System.out.println("a: " + Arrays.toString(a));
System.out.println("b: " + Arrays.toString(b));
System.out.println();
}
}
package p13_lambdy.v3;
// Tego typu kod piszą twórcy "frameworków", gotowych rozwiązań
// Tutaj uzywamy nazw takich jak FunkcjaLiczbowa, oblicz
// - normalne programowanie w Javie.
// Ale robimy to, aby zwykli programiści mieli łatwiej w takich miejscahc jak Uzycie2
public class ZastosowaniaFunkcjiLiczbowej {
// Ta operacja bardzo przypomina map na streamach
// Tutaj zmienia wartość wewnątrz tablicy
public static void zastosujdoTablicy(double[] tab, FunkcjaLiczbowa f) {
for (int i = 0; i < tab.length; i++) {
tab[i] = f.oblicz(tab[i]);
}
}
}
package p14_streamy.a_poczatek;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class A_TypowyPrzyklad {
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println(lista);
System.out.println();
lista.stream()
.filter(s -> s.contains("a"))
.map(s -> s.toUpperCase())
.forEach(s -> System.out.println(s));
// To odpowiada takiej pętli:
for(String s1 : lista) {
if(s1.contains("a")) {
String s2 = s1.toUpperCase();
System.out.println(s2);
}
}
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class Strumienie1 {
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
Stream<String> str1 = lista.stream();
System.out.println(str1);
// Strumień nie jest kolekcją, nie zawiera danych. Jest on tylko sposobem dostępu do danych.
str1.forEach(s -> System.out.print(s + ", "));
System.out.println();
System.out.println();
// Jednego strumienia nie można używać wielokrotnie
// forEach jest "operacją terminującą" i zamyka strumień
//EXN str1.forEach(s -> System.out.print(s + "; "));
// Jest też forEach bezpośrednio na liście (na każdym Iterable)
lista.forEach(s -> System.out.print(s + "; "));
System.out.println();
// Zobaczmy po kolei jakiego typu wyniki wychodzą:
Stream<String> str2a = Arrays.stream(tablica);
Stream<String> str2b = str2a.filter(s -> s.length() > 3);
Stream<String> str2c = str2b.map(s -> s.toUpperCase());
// Stream<Integer> str2d = str2c.map(s -> s.length());
// albo - w praktyce lepiej:
IntStream str2e = str2c.mapToInt(s -> s.length());
// Strumienie liczb oferują dodatkowe operacje.
int suma = str2e.sum();
System.out.println(suma);
System.out.println();
// Zazwyczaj nie tworzy się zmiennych pośrednich, tylko zapisuje jednym ciągiem ("pipeline"):
suma = Arrays.stream(tablica)
.filter(s -> s.length() > 3)
.map(s -> s.toUpperCase())
.mapToInt(s -> s.length())
.sum();
System.out.println(suma);
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
// Operacje wypisują co robią na ekran, abyśmy mogli sprawdzić kolejność ich wykonania.
public class Strumienie2_JakToDziala {
static boolean sprawdz(String s) {
System.out.println("sprawdzam " + s);
return s.length() > 3;
}
static String mapuj(String s) {
System.out.println("mapuję " + s);
return s.toUpperCase();
}
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
// Chociaż wskazuję operacje sprawdź i mapuj w momencie definiowania strumienia
// to one jeszcze się nie wykonują.
Stream<String> strumien = lista.stream()
.filter(s -> sprawdz(s))
.map(s -> mapuj(s));
System.out.println("Strumień utworzony: " + strumien);
lista.add("Dodatkowy");
System.out.println();
System.out.println("Operacja terminująca:");
strumien.forEach(s -> System.out.println(" * " + s));
System.out.println("KONIEC");
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Strumienie2a {
static boolean sprawdz(String s) {
System.out.println("sprawdzam " + s);
return s.length() > 3;
}
static String mapuj(String s) {
System.out.println("mapuję " + s);
return s.toUpperCase();
}
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
Stream<String> strumien = lista.stream()
.filter(s -> sprawdz(s))
.map(s -> mapuj(s))
.limit(5);
System.out.println("Strumień utworzony: " + strumien);
System.out.println();
System.out.println("Operacja terminująca:");
strumien.forEach(s -> System.out.println(" * " + s));
System.out.println("KONIEC");
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Strumienie2b {
static boolean sprawdz(String s) {
System.out.println("sprawdzam " + s);
return s.length() > 3;
}
static String mapuj(String s) {
System.out.println("mapuję " + s);
return s.toUpperCase();
}
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
Stream<String> strumien = lista.stream()
.limit(5)
.filter(s -> sprawdz(s))
.map(s -> mapuj(s));
System.out.println("Strumień utworzony: " + strumien);
System.out.println();
System.out.println("Operacja terminująca:");
strumien.forEach(s -> System.out.println(" * " + s));
System.out.println("KONIEC");
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Strumienie2c {
static boolean sprawdz(String s) {
System.out.println("sprawdzam " + s);
return s.length() > 3;
}
static String mapuj(String s) {
System.out.println("mapuję " + s);
return s.toUpperCase();
}
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
Stream<String> strumien = lista.parallelStream()
.filter(s -> sprawdz(s))
.map(s -> mapuj(s));
System.out.println("Strumień utworzony: " + strumien);
System.out.println();
System.out.println("Operacja terminująca:");
strumien.forEach(s -> System.out.println(" * " + s));
// forEach nie ma obowiązku zachowania kolejności i w przypadku parallelStream nie zachowuje
System.out.println("KONIEC");
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Strumienie2d {
static boolean sprawdz(String s) {
System.out.println("sprawdzam " + s);
return s.length() > 3;
}
static String mapuj(String s) {
System.out.println("mapuję " + s);
return s.toUpperCase();
}
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
Stream<String> strumien = lista.parallelStream()
.filter(s -> sprawdz(s))
.map(s -> mapuj(s));
System.out.println("Strumień utworzony: " + strumien);
System.out.println();
System.out.println("Operacja terminująca:");
// forEachOrdered gwarantuje wykonanie operacji (tylko tej ostatniej) w takiej kolejności, w jakiej elementy są umieszczone w strumieniu
strumien.forEachOrdered(s -> System.out.println(" * " + s));
System.out.println("KONIEC");
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Strumienie2e {
static boolean sprawdz(String s) {
System.out.println("sprawdzam " + s);
return s.length() > 3;
}
static String mapuj(String s) {
System.out.println("mapuję " + s);
return s.toUpperCase();
}
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
Stream<String> strumien = lista.parallelStream()
.filter(s -> sprawdz(s))
.map(s -> mapuj(s))
.limit(5);
// tutaj wciąż te same 5 elementów jest wyświetlanych na końcu
// tak dzieje się dlatego, że strumień jest uporządkowany (ORDERED), bo pochodzi z listy
System.out.println("Strumień utworzony: " + strumien);
System.out.println();
System.out.println("Operacja terminująca:");
strumien.forEach(s -> System.out.println(" * " + s));
System.out.println("KONIEC");
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Strumienie2f {
static boolean sprawdz(String s) {
System.out.println("sprawdzam " + s);
return s.length() > 3;
}
static String mapuj(String s) {
System.out.println("mapuję " + s);
return s.toUpperCase();
}
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
Stream<String> strumien = lista.parallelStream()
.filter(s -> sprawdz(s))
.map(s -> mapuj(s))
.limit(5);
// tutaj wciąż te same 5 elementów jest wyświetlanych na końcu - a ich kolejność będzie zachowana
System.out.println("Strumień utworzony: " + strumien);
System.out.println();
System.out.println("Operacja terminująca:");
strumien.forEachOrdered(s -> System.out.println(" * " + s));
System.out.println("KONIEC");
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Strumienie2g {
static boolean sprawdz(String s) {
System.out.println("sprawdzam " + s);
return s.length() > 3;
}
static String mapuj(String s) {
System.out.println("mapuję " + s);
return s.toUpperCase();
}
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
Stream<String> strumien = lista.parallelStream()
.unordered()
.filter(s -> sprawdz(s))
.map(s -> mapuj(s))
.limit(5);
// unordered - zapomnij o kolejności; to może zwiekszyć wydajność, ale wyniki tego przykładu
// (gdzie mamy limit) są niedetrministyczne
// teraz zmienia się zestaw elementów wyświetlanym na końcu forEachem
System.out.println("Strumień utworzony: " + strumien);
System.out.println();
System.out.println("Operacja terminująca:");
// strumien.forEach(s -> System.out.println(" * " + s));
strumien.forEachOrdered(s -> System.out.println(" * " + s));
System.out.println("KONIEC");
}
}
package p14_streamy.b_dzialanie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Strumienie3_Peek {
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
Stream<String> strumien = lista.stream()
.peek(s -> System.out.println("\n F : " + s))
.filter(s -> s.length() > 3)
.peek(s -> System.out.println(" M : " + s))
.map(String::toUpperCase)
.peek(s -> System.out.println(" # : " + s));
System.out.println("Strumień utworzony: " + strumien);
System.out.println();
System.out.println("Operacja terminująca:");
strumien.forEach(s -> System.out.println(" * " + s));
System.out.println("KONIEC");
System.out.println();
Stream<String> str2a = lista.stream();
Stream<String> str2b = str2a.peek(s -> System.out.println(" % " + s));
// peek nie wpływa na zawartość ani "widzianą z zewnątrz logikę" strumienia,
// ale powoduje, że w momencie ewaluacji strumienia na każdym elemencie będzie wykonan podana operacja
str2b.limit(5).forEach(s -> {});
}
}
package p14_streamy.c_przeglad_operacji;
import java.time.LocalTime;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
public class C01_Generowanie {
static int licznikStatyczny = 0;
public static void main(String[] args) {
Stream<String> str0 = Stream.empty();
str0.forEach(s -> System.out.print(s + ", "));
System.out.println();
Stream<String> str1 = Stream.of("Ala", "Ola", "Ela");
str1.forEach(s -> System.out.print(s + ", "));
System.out.println();
String[] tablica = {"Ala", "Ola", "Ula"};
Stream<String> str2 = Stream.of(tablica);
str2.forEach(s -> System.out.print(s + "; "));
System.out.println();
Stream.Builder<String> builder = Stream.builder();
Stream<String> str3 = builder.add("Ula").add("Ala").add("Ola").build();
str3.forEach(s -> System.out.print(s + ", "));
System.out.println();
System.out.println();
// Kolejny element strumienia generowany "bezkontekstowo" (bez żanego parametru)
Stream<LocalTime> czasy = Stream.generate(() -> LocalTime.now());
// to się zapętla:
// czasy.forEach(lt -> System.out.println(lt));
czasy.limit(20).forEach(lt -> System.out.println(lt));
//EXN przy probie kolejnego uzycia
// czasy.limit(30).forEach(lt -> System.out.println(lt));
System.out.println();
int licznikLokalny = 0;
// w wyrażeniu lambda nie wolno modyfikować zmiennych lokalnych ani używać zmieniających się zmiennych lokalnych
// int suma0 = IntStream.generate(() -> ++licznikLokalny).limit(10).sum();
int suma = IntStream.generate(() -> ++licznikStatyczny)
.filter(x -> x%2 == 1)
.limit(8)
.sum();
System.out.println(suma);
// Kolejny element generowany na podstawie poprzedniego
Stream<String> str4 = Stream.iterate("$", s -> s + "*");
// też nieskończony
str4.limit(10).forEach(System.out::println);
System.out.println();
// Przykład sensownych operacji na strumieniach nieskończonych:
IntStream parzyste = IntStream.iterate(0, x -> x+2);
IntStream nieparzyste = parzyste.map(x -> x+1);
int suma2 = nieparzyste.limit(9).sum();
System.out.println(suma2);
System.out.println();
IntStream.iterate(1, x -> x+2).limit(10).forEach(System.out::println);
System.out.println();
LongStream.iterate(1, x -> 2*x).limit(65).forEach(System.out::println);
System.out.println();
Stream<String> str11 = Stream.of("Ala", "Ola", "Ela");
Stream<String> str12 = Stream.of("Adam", "Ludwik", "Ksawery");
Stream<String> razem = Stream.concat(str11, str12);
razem.forEach(s -> System.out.print(s + ", "));
System.out.println();
}
}
package p14_streamy.c_przeglad_operacji;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.Collator;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Stream;
public class C02_ZRoznychKlas {
public static void main(String[] args) {
Random random = new Random();
// nieskończony strumień losowych intów
random.ints();
random.ints().limit(100).forEach(System.out::println);
// przykład: utwórz tablicę 100 losowych int-ów:
int[] liczbyLosowe = random.ints().limit(100).toArray();
System.out.println(Arrays.toString(liczbyLosowe));
System.out.println();
//random.doubles();
int suma = random.ints(100, 0, 1000).sum();
System.out.println(suma);
System.out.println();
try {
// operacja "imperatywna":
// List<String> wczytaneLinie = Files.readAllLines(path);
// dostęp strumieniowy
// strumienie też można zamykać; ten należy zamykać
try(Stream<String> lines = Files.lines(Paths.get("pan-tadeusz.txt"))) {
lines.filter(s -> s.contains("Tadeusz"))
.sorted(Collator.getInstance())
.forEachOrdered(System.out::println);
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println();
Path dir = Paths.get("src");
try {
Files.list(dir)
.forEach(f -> System.out.println(f + " " + Files.isRegularFile(f)));
} catch (IOException e) {
e.printStackTrace();
}
}
}
package p14_streamy.c_przeglad_operacji;
import java.util.stream.Stream;
public class C11_FilterMap {
public static void main(String[] args) {
String[] imiona = {"Ala", "Ola", "Basia", "Kasia", "Ela", "Ula", "Agnieszka", "Magdalena", "Anna", "Hanna", "Joanna", "Ala", "Agata", "Genowefa", "Grażyna", "Karolina", "Julia", "Zuzanna"};
Stream.of(imiona)
.filter(s -> s.length() >= 5)
.forEach(System.out::println);
System.out.println();
Stream.of(imiona)
.map(String::toUpperCase)
.forEach(System.out::println);
System.out.println();
Stream.of(imiona)
.filter(s -> s.startsWith("A"))
.map(String::length) // Stream<String> -> Stream<Integer>
.forEach(System.out::println);
Stream.of(imiona)
.filter(s -> s.startsWith("A"))
.mapToInt(String::length) // Stream<String> -> IntStream
.forEach(System.out::println);
}
}
package p14_streamy.c_przeglad_operacji;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class C12_FlatMap {
static List<Integer> generuj(int ilosc) {
List<Integer> lista = new ArrayList<>();
for(int i = 1; i <= ilosc; i++) {
lista.add(i);
}
return lista;
}
static Stream<Integer> generujStrumien(int ilosc) {
List<Integer> lista = new ArrayList<>();
for(int i = 1; i <= ilosc; i++) {
lista.add(i);
}
return lista.stream();
}
static IntStream generujStrumienIntow(int ilosc) {
List<Integer> lista = new ArrayList<>();
for(int i = 1; i <= ilosc; i++) {
lista.add(i);
}
return lista.stream().mapToInt(Integer::intValue);
}
public static void main(String[] args) {
System.out.println(generuj(1));
System.out.println(generuj(3));
System.out.println(generuj(5));
System.out.println();
System.out.println("Elementy strumienia wejściowego:");
Stream.of(1, 3, 5)
.forEach(x -> System.out.print(x + " | "));
System.out.println();
System.out.println();
System.out.println("Zwykłe mapowanie:");
Stream.of(1, 3, 5)
.map(C12_FlatMap::generuj)
.forEach(x -> System.out.print(x + " | "));
System.out.println();
Stream.of(1, 3, 5)
.map(x -> C12_FlatMap.generuj(x).stream())
.forEach(x -> System.out.print(x + " | "));
System.out.println();
System.out.println();
System.out.println("Płaskie mapowanie:");
Stream.of(1, 3, 5)
.flatMap(x -> C12_FlatMap.generuj(x).stream())
.forEach(x -> System.out.print(x + " | "));
System.out.println();
System.out.println();
Stream.of(1, 3, 5)
.flatMap(C12_FlatMap::generujStrumien)
.forEach(x -> System.out.print(x + " | "));
System.out.println();
System.out.println();
int suma = Stream.of(1, 3, 5)
.flatMapToInt(C12_FlatMap::generujStrumienIntow)
.sum();
System.out.println(suma);
}
}
package p14_streamy.c_przeglad_operacji;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class C13_RozneOperacje {
public static void main(String[] args) {
String[] imiona = {"Ala", "Ola", "Basia", "Kasia", "Ela", "Ula", "Agnieszka", "Magdalena", "Anna", "Hanna", "Joanna", "Ala", "Agata", "Genowefa", "Grażyna", "Karolina", "Julia", "Zuzanna"};
// ** operacje terminujące ** //
// forEach - dla każdego elementu wykonaj akcję
Stream.of(imiona).forEach(s -> System.out.println(s));
// forEachOrdered - dla każdego elementu wykonaj akcję zachowując kolejność (istotne dla parallelStream)
Stream.of(imiona).forEachOrdered(s -> System.out.println(s));
System.out.println("\n--------------------------------\n");
// count() - liczba elementów strumienia (też wymaga pobrania elementów !)
long n = Stream.of(imiona).count();
System.out.println("count: " + n);
// toArray - tworzy nową tablicę i wstawia tam elementy
Object[] array1 = Stream.of(imiona)
.map(String::toLowerCase)
.toArray();
System.out.println(array1 + " , length="+array1.length);
System.out.println(Arrays.toString(array1));
System.out.println();
// inna wersja: podajemy funkcję tworzącą tablice; korzyść: dostajemy String[] a nie Object[]
String[] array2 = Stream.of(imiona)
.sorted()
.toArray(String[]::new);
System.out.println(array2 + " , length="+array2.length);
System.out.println(Arrays.toString(array2));
System.out.println("\n--------------------------------\n");
// reduce - redukcja w sposób właściwy dla klas niemutowalnych
Optional<String> wynik01 = Stream.of(imiona)
.reduce(String::concat);
System.out.println("wynik01: " + wynik01);
String wynik02 = Stream.of(imiona)
.reduce("", String::concat);
System.out.println("wynik02: " + wynik02);
String wynik03 = Stream.of(imiona)
.reduce("|", String::concat);
System.out.println("wynik03: " + wynik03);
String wynik04 = Stream.of(imiona)
.parallel()
.reduce("|", String::concat);
System.out.println("wynik04: " + wynik04);
// Takie użycie concat jest niewydaje i tego nie naśladujcie
// wersja, w której typ wyniku może być inny niż typ elementów
// tu przykład sumowania długości napisów
Integer wynik05 = Stream.of(imiona)
.reduce(0, (x, s) -> x+s.length(), (x,y)->x+y);
System.out.println("wynik05: " + wynik05);
System.out.println();
// collect - redukcja w sposób właściwy dla klas mutowalnych
StringBuilder wynik06 = Stream.of(imiona).collect(
StringBuilder::new, // supplier - tworzy początkową "pusta" wartość
StringBuilder::append, // accumulator - aktualizuje wartość na podstawie elementu strumienia
StringBuilder::append); // combiner - łączy częściowe wyniki (które mogą się pojawić gdy mamy parallelStream)
System.out.println("wynik06: " + wynik06);
List<String> lista = Stream.of(imiona)
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(lista);
System.out.println("\n--------------------------------\n");
// findFirst i findAny - wybór jednego elementu
// findAny zwraca "jakikolwiek" - ale to nie znaczy "losowy"
// po prostu implementacja zwróci ten, do którego ma najszybszy dostęp
Optional<String> wynik07 = Stream.of(imiona).findFirst();
Optional<String> wynik08 = Stream.of(imiona).findAny();
Optional<String> wynik09 = Stream.of(imiona).parallel().findAny(); // niedeterministyczne, czasami była Ala a czasami Ula
// jest szansa na zobaczenie innego imienia niż Ala :)
System.out.println("findFirst : " + wynik07);
System.out.println("findAny : " + wynik08);
System.out.println("findAny par: " + wynik09);
System.out.println();
// kwantyfikatory logiczne - zwracają true albo false
// działają w sposób leniwy - przestają pobierać kolejne elementy strumienia jeśli wynik jest rozstrzygnięty
boolean bool1 = Stream.of(imiona).allMatch(s -> s.endsWith("a"));
System.out.println("bool1 = " + bool1);
boolean bool2 = Stream.of(imiona).allMatch(s -> s.startsWith("K"));
System.out.println("bool2 = " + bool2);
boolean bool3 = Stream.of(imiona).anyMatch(s -> s.startsWith("K"));
System.out.println("bool3 = " + bool3);
boolean bool4 = Stream.of(imiona).noneMatch(s -> s.startsWith("K"));
System.out.println("bool4 = " + bool4);
}
}
package p14_streamy.c_przeglad_operacji;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import emps.Employee;
import emps.ObslugaCSV;
public class C14_MinMax {
public static void main(String[] args) {
List<Employee> lista = ObslugaCSV.wczytaj("emps.csv");
Optional<Employee> min = lista.stream().min(Comparator.comparing(Employee::getSalary));
Optional<Employee> max = lista.stream().max(Comparator.comparing(Employee::getSalary));
System.out.println("min: " + min);
System.out.println("max: " + max);
System.out.println();
if(min.isPresent()) {
System.out.println("Znaleziono minimum:");
Employee emp = min.get();
System.out.println(emp.getFirstName() + " " + emp.getLastName() + " zarabia " + emp.getSalary());
} else {
System.out.println("nie ma minimum");
}
if(max.isPresent()) {
System.out.println("Znaleziono maximum:");
Employee emp = max.get();
System.out.println(emp.getFirstName() + " " + emp.getLastName() + " zarabia " + emp.getSalary());
} else {
System.out.println("nie ma maximum");
}
System.out.println();
String [] stanowiska = {"Programmer", "Shipping Clerk", "Brygadier"};
for (String stanowisko : stanowiska) {
String tekst = lista.stream()
.filter(emp -> Objects.equals(emp.getJobTitle(), stanowisko))
.max(Comparator.comparing(Employee::getSalary))
.map(emp -> emp.getFirstName() + " " + emp.getLastName() + " zarabia " + emp.getSalary())
.orElse("nie ma takiego gościa");
// powyższe map dotyczy Optional, a nie Stream
System.out.println("Najbogatszy " + stanowisko + ": " + tekst);
}
}
}
package p14_streamy.c_przeglad_operacji;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class C21_DistinctSorted {
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Magdalena", "Joanna", "Anna", "Teresa", "Ola",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
// distinct i sorted to są opearacje "stateful intermediate"
// one są wykonywane dopiero gdy na strumieniu jest odpalona operacja terminalna
// ale mogą wymagać zebrania większej ilości danych (nawet wszystkich) przed przepuszczeniem elementów do dalszych etapów przetwarzania
// Wynika z tego, że nie powinny być stosowane do strumieni nieskończonych.
String napis = lista.stream()
.distinct()
.map(String::toUpperCase)
.sorted()
.collect(Collectors.joining(", "));
System.out.println(napis);
}
}
package p14_streamy.c_przeglad_operacji;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class C22_DistinctSorted {
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Ala", "Magdalena", "Ola", "Joanna", "Anna", "Teresa", "Ola",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
// distinct i sorted to są opearacje "stateful intermediate"
// one są wykonywane dopiero gdy na strumieniu jest odpalona operacja terminalna
// ale mogą wymagać zebrania większej ilości danych (nawet wszystkich) przed przepuszczeniem elementów do dalszych etapów przetwarzania
// Wynika z tego, że nie powinny być stosowane do strumieni nieskończonych.
String napis = lista.stream()
.map(String::toUpperCase)
.peek(s -> System.out.println("start " + s))
.distinct()
.peek(s -> System.out.println("za distinct " + s))
.sorted()
.peek(s -> System.out.println("za sorted " + s))
.collect(Collectors.joining(", "));
System.out.println();
System.out.println(napis);
}
}
package p14_streamy.c_przeglad_operacji;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class C23_DistinctSorted {
public static void main(String[] args) {
String[] tablica = { "Ala", "Ola", "Iwona", "Ala", "Magdalena", "Ola", "Joanna", "Anna", "Teresa", "Ola",
"Żaneta", "Ęcki", "Ącki", "Agnieszka", "ala", "Łucja", "Julia", "Julitta", "Zuzanna" };
List<String> lista = new ArrayList<>(Arrays.asList(tablica));
System.out.println("Przed tworzeniem strumienia");
// distinct i sorted to są opearacje "stateful intermediate"
// one są wykonywane dopiero gdy na strumieniu jest odpalona operacja terminalna
// ale mogą wymagać zebrania większej ilości danych (nawet wszystkich) przed przepuszczeniem elementów do dalszych etapów przetwarzania
// Wynika z tego, że nie powinny być stosowane do strumieni nieskończonych.
String napis = lista.parallelStream()
.map(String::toUpperCase)
.peek(s -> System.out.println("start " + s))
.distinct()
.peek(s -> System.out.println("za distinct " + s))
.sorted()
.peek(s -> System.out.println("za sorted " + s))
.collect(Collectors.joining(", "));
System.out.println();
System.out.println(napis);
}
}
package p14_streamy.c_przeglad_operacji;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
public class C31_TypyProste {
public static void main(String[] args) {
DoubleStream losowe = DoubleStream.generate(Math::random);
losowe.limit(100).forEach(x -> System.out.print(x + ", "));
System.out.println();
Random random = new Random();
double sumaLosowych1 = random.doubles().limit(10).sum();
System.out.println(sumaLosowych1);
random.ints(10, 100, 200).forEach(x -> System.out.print(x + ", "));
System.out.println();
LongStream potegi = LongStream.iterate(1, x -> x*2);
potegi.limit(65).forEach(x -> System.out.println(x));
System.out.println();
IntStream.range(0, 10).forEach(x -> System.out.print(x + ", "));
System.out.println();
IntStream.rangeClosed(0, 10).forEach(x -> System.out.print(x + ", "));
IntStream str_int = IntStream.rangeClosed(0, 10);
// tłumaczenie między strumieniem intów a strumieniem Integerów:
Stream<Integer> str_Integer = str_int.boxed();
IntStream str_int2 = str_Integer.mapToInt(Integer::intValue);
// IntStream str_int3 = str_Integer.mapToInt(x -> x);
List<Integer> liczby = IntStream.range(0, 100)
.map(i -> i*i)
.boxed() // zmienia IntStream na Stream<Integer>
.collect(Collectors.toList());
System.out.println(liczby);
}
}
package p14_streamy.d_redukcje_i_grupowanie;
import java.util.stream.Stream;
/* collect i reduce to dwa schematy służące do agregacji danych strumienia,
* czyli "zbierania danych" tak, aby na podstawie całego zestawu danych uzyskać pojedynczy wynik.
*
* collect i Collectory - schemat agregacji wykorzystujący klasy mutowalne,
* jako krok operacji podaje się metodę typu void
*
* reduce - schemat agregacji wykorzystujący klasy niemutowalne lub wartości liczbowe
* jako krok operacji podaje się metodę zwracającą wynik
*/
public class Collect_i_Reduce {
public static void main(String[] args) {
String[] imiona = {"Ala", "Ola", "Ela"};
{
StringBuilder wynik = Stream.of(imiona).collect(
StringBuilder::new, // supplier - tworzy początkową "pustą" wartość
StringBuilder::append, // accumulator - aktualizuje wartość na podstawie elementu strumienia
StringBuilder::append); // combiner - łączy częściowe wyniki (które mogą się pojawić gdy mamy parallelStream)
System.out.println("1: " +wynik);
}
// w przypadku strumienia sekwencyjnego można to przetłumaczyć na taką pętlę:
{
StringBuilder wynik = new StringBuilder();
for (String s : imiona) {
wynik.append(s); // tylko wywołanie, wynik tej metody nie jest brany pod uwagę, może być void
}
System.out.println("2: " + wynik);
}
// #################
// Klasa, o którą się opieramy, musi być mutowalna, a operacja (w tym przypadku append)
// musi zmieniać obiekt, na którym jest wołana
// To nie zadziała:
{
String wynik = Stream.of(imiona).collect(
String::new,
String::concat, // concat nie zmienia Strina, na którym jest wołany - więc nie będzie efektu
String::concat);
System.out.println("3: " + wynik);
}
// Dla klas niemutowalnych (i typów prostych) właściwym schematem jest reduce:
{
String wynik = Stream.of(imiona).reduce(
"",
String::concat);
System.out.println("4: " + wynik);
}
// to tłumaczy się na taką pętlę:
{
String wynik = "";
for (String s : imiona) {
wynik = wynik.concat(s); // przypisanie / podmiana wyniku !!!
}
System.out.println("5: " + wynik);
}
// Gdyby "combiner" częściowych wyników różnił się od "accumulatora" pojedynczych wartości,
// podajemy go jako trzeci parametr
{
String wynik = Stream.of(imiona).reduce(
"",
String::concat,
String::concat);
System.out.println("6: " + wynik);
}
// Tu jest taka sytuacja, bo na wejściu mamy strumień Stringów,
// a wynikiem jest int
// pierwsza funkcja jest typu (int, String) -> int
// a druga jest typu (int, int) -> int
{
int wynik = Stream.of(imiona).reduce(
0,
(suma, str) -> suma + str.length(),
Math::addExact);
System.out.println("7: " + wynik);
}
// te ostatnie funkcje ("combiner") są używane tylko gdy parallelStream
}
}
package p14_streamy.d_redukcje_i_grupowanie;
import java.util.Collections;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
/* Przykład własnej definicji Collectora.
* Tylko, aby pokazać, jak one działają.
* Collector o funkcjonalności łączenia napisów istnieje: Collectors.joining();
*/
public class CollectorLaczacyNapisy implements Collector<String, StringBuilder, String> {
@Override
public Supplier<StringBuilder> supplier() {
// nie tak: return new StringBullder();
return StringBuilder::new;
}
@Override
public BiConsumer<StringBuilder, String> accumulator() {
return StringBuilder::append; // append(String)
}
@Override
public BinaryOperator<StringBuilder> combiner() {
return StringBuilder::append; // append(StringBuilder)
}
@Override
public Function<StringBuilder, String> finisher() {
return StringBuilder::toString;
}
@Override
public Set<Characteristics> characteristics() {
return Collections.emptySet();
}
}
package p14_streamy.d_redukcje_i_grupowanie;
import java.util.stream.Collector;
import java.util.stream.Collector.Characteristics;
import java.util.stream.Stream;
public class Collector_Test {
public static void main(String[] args) {
String[] imiona = {"Ala", "Ola", "Ela"};
CollectorLaczacyNapisy collector1 = new CollectorLaczacyNapisy();
String wynik1 = Stream.of(imiona).collect(collector1);
System.out.println(wynik1);
// Ale to samo można zrobić bezpośrednio w kodzie:
// Najpierw wersja, że akumulator staje się wynikiem - nie ma funkcji finisher
Collector<String, StringBuilder, StringBuilder> collector2 =
Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append);
StringBuilder wynik2 = Stream.of(imiona).collect(collector2);
System.out.println(wynik2);
// Dodaję finisher równy StringBuilder.toString - ostateczny wynik typu String
Collector<String, StringBuilder, String> collector3 =
Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString);
String wynik3 = Stream.of(imiona).collect(collector3);
System.out.println(wynik3);
}
}
package p14_streamy.d_redukcje_i_grupowanie;
import java.util.Collection;
import java.util.Comparator;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import emps.Employee;
import emps.ObslugaCSV;
public class Kolektory1 {
public static void main(String[] args) {
//List<Employee> emps = Collections.emptyList();
List<Employee> emps = ObslugaCSV.wczytaj("emps.csv");
// collectory obliczające standardowe funkcje agregujące
Long ilu = emps.stream().collect(Collectors.counting());
Integer suma = emps.stream().collect(Collectors.summingInt(Employee::getSalary));
Double avg = emps.stream().collect(Collectors.averagingInt(Employee::getSalary));
// dla pustego zbioru danych wychodzi 0.0
System.out.println(ilu + ", " + suma + ", " + avg);
// Porównuje pracowników wg pensji
Comparator<Employee> komp = Comparator.comparingInt(Employee::getSalary);
Optional<Employee> min = emps.stream().collect(Collectors.minBy(komp));
Optional<Employee> max = emps.stream().collect(Collectors.maxBy(komp));
System.out.println(min);
System.out.println(max);
// przykład wyciągaia wartości z Optionala
String str1 = min
.map(emp -> emp.getFirstName()
+ " " + emp.getLastName()
+ " / " + emp.getSalary())
.orElse("nie ma takiego gościa");
System.out.println(str1);
System.out.println();
// Oblicza wszystkie 5 standardowe funkcje agregujące
IntSummaryStatistics statystyki = emps.stream().collect(Collectors.summarizingInt(Employee::getSalary));
System.out.println(statystyki);
System.out.println(statystyki.getAverage());
System.out.println();
// Zestaw kolektorów zbierających dane do kolekcji:
List<String> list1 = emps.stream()
.map(Employee::getFirstName)
.sorted()
.distinct()
.collect(Collectors.toList());
System.out.println(list1);
Set<String> set1 = emps.stream()
.map(Employee::getCity)
.collect(Collectors.toSet());
System.out.println(set1);
Collection<String> kolekcja = emps.stream()
.map(Employee::getCity)
.collect(Collectors.toCollection(TreeSet::new));
System.out.println(kolekcja);
System.out.println();
// Tworząc słownik podajemy skąd się biorą klucze, skąd się biorą wartości
// i ewentualnie jak aktualizować już wpisane wartości
Map<String, Integer> grupy = emps.stream()
.collect(Collectors.toMap(Employee::getCity,
Employee::getSalary,
Math::addExact));
grupy.forEach((k,v) -> System.out.printf("%20s -> %10s\n", k, v));
System.out.println();
String txt1 = emps.stream()
.map(Employee::getDepartmentName)
.distinct()
.collect(Collectors.joining());
System.out.println(txt1);
String txt2 = emps.stream()
.map(Employee::getDepartmentName)
.distinct()
.collect(Collectors.joining(", "));
System.out.println(txt2);
String txt3 = emps.stream()
.map(Employee::getDepartmentName)
.distinct()
.collect(Collectors.joining(", ", "<", ">"));
System.out.println(txt3);
}
}
package p14_streamy.d_redukcje_i_grupowanie;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
import emps.Employee;
import emps.ObslugaCSV;
public class Kolektory2 {
public static void main(String[] args) {
//List<Employee> emps = Collections.emptyList();
List<Employee> emps = ObslugaCSV.wczytaj("emps.csv");
// grouping by - zbiera elementy w grupy
Map<String, List<Employee>> grupy1 = emps.stream()
.collect(Collectors.groupingBy(Employee::getJobTitle));
grupy1.forEach((k,v) -> {
System.out.println(k);
v.forEach(emp -> {
System.out.printf(" %-12s %-12s %10s\n", emp.getFirstName(), emp.getLastName(), emp.getSalary());
});
});
System.out.println();
// Podajemy dodatkowy kolektor mówiący co robić z każdą grupą
Map<String, Integer> grupy2 = emps.stream()
.collect(Collectors.groupingBy(
Employee::getJobTitle,
Collectors.summingInt(Employee::getSalary)));
grupy2.forEach((k,v) -> {
System.out.printf("%-32s %12s\n", k, v);
});
System.out.println();
// Możemy też podać fabrykę map jako środkowy parametr
Map<String, Integer> grupy3 = emps.stream()
.collect(Collectors.groupingBy(
Employee::getJobTitle,
TreeMap::new,
Collectors.summingInt(Employee::getSalary)));
grupy3.forEach((k,v) -> {
System.out.printf("%-32s %12s\n", k, v);
});
System.out.println();
System.out.println("================");
Map<Boolean, List<Employee>> partycje1 = emps.stream()
.collect(Collectors.partitioningBy(emp -> emp.getSalary() >= 10000));
System.out.println("Bogaci:");
partycje1.get(true)
.forEach(emp -> System.out.println(" " + emp.getLastName()));
System.out.println("\nBiedni:");
partycje1.get(false)
.forEach(emp -> System.out.println(" "+ emp.getLastName()));
System.out.println();
Map<Boolean, Long> partycje2 = emps.stream()
.collect(Collectors.partitioningBy(
emp -> emp.getSalary() >= 10000,
Collectors.counting()));
System.out.println("Bogatych " + partycje2.get(true));
System.out.println("Biednych " + partycje2.get(false));
}
}
package p14_streamy.d_redukcje_i_grupowanie;
import java.math.BigInteger;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
public class Silnia_Reduce {
static long silniaFun(int n) {
return LongStream.rangeClosed(2, n)
.reduce(1L, (a, i) -> a * i);
}
static long silniaKlasyczna(int n) {
// działa jak taka pętla:
long a = 1L;
for(int i = 2; i <= n; i++) {
a = a * i;
}
return a;
}
static long silniaFun2(int n) {
return LongStream.rangeClosed(2, n)
.reduce(1, Math::multiplyExact);
}
static BigInteger silniaFunBig(int n) {
return IntStream.rangeClosed(2, n)
.mapToObj(BigInteger::valueOf)
.reduce(BigInteger.ONE, BigInteger::multiply);
}
public static void main(String[] args) {
System.out.println(silniaFun(5));
System.out.println(silniaFun2(5));
try {
System.out.println(silniaFun2(21));
} catch (Exception e) {
System.out.println("overflow");
}
System.out.println(silniaFunBig(5));
System.out.println(silniaFunBig(100));
}
}
package p15_parallel_stream.a;
import java.util.Arrays;
import java.util.function.IntUnaryOperator;
import java.util.stream.IntStream;
public class SprawdzanieIleWatkow1 {
public static void main(String[] args) {
IntUnaryOperator operacja = x -> {
System.out.println(Thread.currentThread().getId());
return 2*x;
};
int[] tab = new int[100];
Arrays.fill(tab, 33);
System.out.println("Sekwencyjnie:");
int suma1 = IntStream.of(tab).map(operacja).sum();
System.out.println("suma1 = " + suma1);
System.out.println();
System.out.println("Parallel:");
int suma2 = IntStream.of(tab).parallel().map(operacja).sum();
System.out.println("suma2 = " + suma2);
}
}
package p15_parallel_stream.a;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.function.IntUnaryOperator;
import java.util.stream.IntStream;
public class SprawdzanieIleWatkow2 {
public static void main(String[] args) {
AtomicIntegerArray array = new AtomicIntegerArray(50);
IntUnaryOperator operacja = x -> {
int id = (int)Thread.currentThread().getId();
array.incrementAndGet(id);
return 2*x;
};
int[] tab = new int[1_000_000];
Arrays.fill(tab, 33);
System.out.println("Tablica wątków na początku:");
System.out.println(array);
int suma2 = IntStream.of(tab).parallel().map(operacja).sum();
System.out.println("suma2 = " + suma2);
System.out.println();
System.out.println("Tablica wątków na końcu:");
System.out.println(array);
int ileWatkow = 0;
for (int i = 0; i < array.length(); i++) {
if(array.get(i) > 0) {
ileWatkow++;
System.out.printf("wątek nr %3d - %8d razy\n", i, array.get(i));
}
}
System.out.println();
System.out.println("W sumie pracowało " + ileWatkow + " wątków.");
System.out.println("Ilość procesorów: " +
Runtime.getRuntime().availableProcessors());
}
}
package p15_parallel_stream.a;
import java.util.Random;
import java.util.function.LongSupplier;
import java.util.stream.LongStream;
public class SumArray {
static final int N = 120_000_000;
static final int MAX = 1000;
static final int POWTORZENIA = 40;
static long[] tab;
public static void main(String[] args) {
System.out.println("Generuje dane");
tab = new long[N];
wylosuj();
System.out.println("pętla");
testuj(SumArray::petla);
System.out.println("stream");
testuj(SumArray::sekw);
System.out.println("parallel stream");
testuj(SumArray::parallel);
System.out.println();
System.out.println("pętla");
testuj(POWTORZENIA, SumArray::petla);
System.out.println("stream");
testuj(POWTORZENIA, SumArray::sekw);
System.out.println("parallel stream");
testuj(POWTORZENIA, SumArray::parallel);
}
private static void testuj(LongSupplier metoda) {
long start = System.currentTimeMillis();
long wynik = metoda.getAsLong();
long end = System.currentTimeMillis();
System.out.printf("czas: %6d, wynik: %15d\n", end - start, wynik);
}
private static void testuj(int n, LongSupplier metoda) {
long start = System.currentTimeMillis();
long wynik = 0L;
for(int i = 1; i <= n; i++) {
wynik += metoda.getAsLong();
}
long end = System.currentTimeMillis();
System.out.printf("czas: %6d, wynik: %15d\n", end - start, wynik);
}
private static void wylosuj() {
Random r = new Random();
for (int i = 0; i < tab.length; i++) {
tab[i] = r.nextInt(MAX);
}
}
private static long petla() {
long suma = 0L;
for (int i = 0; i < tab.length; i++) {
suma += tab[i];
}
return suma;
}
private static long sekw() {
return LongStream.of(tab).sum();
}
private static long parallel() {
return LongStream.of(tab).parallel().sum();
}
}
package p15_parallel_stream.b_spliterator;
import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;
public class ArrayListSplit {
public static void main(String[] args) {
List<String> lista = new ArrayList<>();
lista.add("aaa");
lista.add("bbb");
lista.add("ccc");
lista.add("ddd");
lista.add("eee");
lista.add("fff");
lista.add("ggg");
lista.add("hhh");
lista.add("iii");
lista.add("jjj");
System.out.println(lista);
Consumer<String> akcja = s -> System.out.println("* " + s);
System.out.println("Pętla tryAdvance:");
Spliterator<String> spliterator1 = lista.spliterator();
while(spliterator1.tryAdvance(akcja));
System.out.println();
System.out.println("forEachRemaining:");
Spliterator<String> spliterator2 = lista.spliterator();
spliterator2.forEachRemaining(akcja);
System.out.println();
System.out.println("trySplit 2 poziomy:");
Spliterator<String> spliterator3 = lista.spliterator();
System.out.println("estimate size: " + spliterator3.estimateSize());
Spliterator<String> spliterator3a = spliterator3.trySplit();
System.out.println("Oryginalny:");
spliterator3.forEachRemaining(akcja);
System.out.println("wynik pierwszego split:");
spliterator3a.forEachRemaining(akcja);
System.out.println();
System.out.println("trySplit 3 poziomy:");
Spliterator<String> spliterator4 = lista.spliterator();
System.out.println("estimate size: " + spliterator4.estimateSize());
Spliterator<String> spliterator4a = spliterator4.trySplit();
Spliterator<String> spliterator4b = spliterator4.trySplit();
System.out.println("Oryginalny:");
spliterator4.forEachRemaining(akcja);
System.out.println("wynik pierwszego split:");
spliterator4a.forEachRemaining(akcja);
System.out.println("wynik drugiego split:");
spliterator4b.forEachRemaining(akcja);
System.out.println();
}
}
package p15_parallel_stream.b_spliterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;
// Morał: LinkedList nie dzieli się na fragmenty, więc operacje nie będą zrównoleglane
public class LinkedListSplit {
public static void main(String[] args) {
List<String> lista = new LinkedList<>();
lista.add("aaa");
lista.add("bbb");
lista.add("ccc");
lista.add("ddd");
lista.add("eee");
lista.add("fff");
lista.add("ggg");
lista.add("hhh");
lista.add("iii");
lista.add("jjj");
System.out.println(lista);
Consumer<String> akcja = s -> System.out.println("* " + s);
System.out.println("Pętla tryAdvance:");
Spliterator<String> spliterator1 = lista.spliterator();
while(spliterator1.tryAdvance(akcja));
System.out.println();
System.out.println("forEachRemaining:");
Spliterator<String> spliterator2 = lista.spliterator();
spliterator2.forEachRemaining(akcja);
System.out.println();
System.out.println("trySplit 2 poziomy:");
Spliterator<String> spliterator3 = lista.spliterator();
System.out.println("estimate size: " + spliterator3.estimateSize());
Spliterator<String> spliterator3a = spliterator3.trySplit();
System.out.println("Oryginalny:");
spliterator3.forEachRemaining(akcja);
System.out.println("wynik pierwszego split:");
spliterator3a.forEachRemaining(akcja);
System.out.println();
System.out.println("trySplit 3 poziomy:");
Spliterator<String> spliterator4 = lista.spliterator();
System.out.println("estimate size: " + spliterator4.estimateSize());
Spliterator<String> spliterator4a = spliterator4.trySplit();
Spliterator<String> spliterator4b = spliterator4.trySplit();
System.out.println("4a " + spliterator4a);
System.out.println("4b " + spliterator4b); // null
System.out.println("Oryginalny:");
spliterator4.forEachRemaining(akcja);
System.out.println("wynik pierwszego split:");
spliterator4a.forEachRemaining(akcja);
// NPE
// System.out.println("wynik drugiego split:");
// spliterator4b.forEachRemaining(akcja);
System.out.println();
}
}
package p15_parallel_stream.b_spliterator;
import java.util.function.LongSupplier;
public class MierzenieCzasu {
public static void uruchom(LongSupplier metoda) {
long start = System.nanoTime();
long wynik = metoda.getAsLong();
long end = System.nanoTime();
System.out.printf("czas: %12d , wynik = %d\n", (end - start) / 1000, wynik);
}
public static void uruchom(int n, LongSupplier metoda) {
long start = System.currentTimeMillis();
long wynik = 0L;
for(int i = 1; i <= n; i++) {
wynik += metoda.getAsLong();
}
long end = System.currentTimeMillis();
System.out.printf("czas: %6d, wynik: %15d\n", end - start, wynik);
}
}
package p15_parallel_stream.b_spliterator;
import java.util.Spliterator;
import java.util.function.Consumer;
public class SpliteratorLiczbyNieparzyste implements Spliterator<Integer> {
private int max;
private int min;
// domyślnie 100 liczb
public SpliteratorLiczbyNieparzyste() {
this(100);
}
public SpliteratorLiczbyNieparzyste(int ile) {
this(0, ile);
}
private SpliteratorLiczbyNieparzyste(int min, int max) {
this.min = min;
this.max = max;
}
private int next() {
return 1 + 2 * min++;
}
private boolean hasNext() {
return min < max;
}
@Override
public boolean tryAdvance(Consumer<? super Integer> action) {
if(hasNext()) {
action.accept(this.next());
return true;
} else {
return false;
}
}
@Override
public SpliteratorLiczbyNieparzyste trySplit() {
int middle = (max + min) / 2;
SpliteratorLiczbyNieparzyste nowy = new SpliteratorLiczbyNieparzyste(min, middle);
min = middle;
return nowy;
}
@Override
public long estimateSize() {
return max - min;
}
@Override
public int characteristics() {
return ORDERED | DISTINCT | SIZED | SUBSIZED | NONNULL;
}
}
package p15_parallel_stream.b_spliterator;
import java.util.Spliterator;
import java.util.function.Consumer;
public class SpliteratorPowolny implements Spliterator<Integer> {
private int max;
private int min;
private int niepotrzebne;
private final int SPOWOLNIENIE = 10000;
// domyślnie 100 liczb
public SpliteratorPowolny() {
this(100);
}
public SpliteratorPowolny(int ile) {
this(0, ile);
}
private SpliteratorPowolny(int min, int max) {
this.min = min;
this.max = max;
}
private int next() {
for(int i=0; i<SPOWOLNIENIE; i++) {
niepotrzebne++;
}
return 1 + 2 * min++;
}
private boolean hasNext() {
return min < max;
}
@Override
public boolean tryAdvance(Consumer<? super Integer> action) {
action.accept(this.next());
return hasNext();
}
@Override
public SpliteratorPowolny trySplit() {
int middle = (max + min) / 2;
SpliteratorPowolny nowy = new SpliteratorPowolny(min, middle);
min = middle;
return nowy;
}
@Override
public long estimateSize() {
return max - min;
}
@Override
public int characteristics() {
return ORDERED | DISTINCT | SIZED | SUBSIZED | NONNULL;
}
}
package p15_parallel_stream.b_spliterator;
import java.util.Spliterator;
import java.util.function.IntConsumer;
public class SpliteratorPrimitive implements Spliterator.OfInt {
private int max;
private int min;
// domyślnie 100 liczb
public SpliteratorPrimitive() {
this(100);
}
public SpliteratorPrimitive(int ile) {
this(0, ile);
}
private SpliteratorPrimitive(int min, int max) {
this.min = min;
this.max = max;
}
private int next() {
return 1 + 2 * min++;
}
private boolean hasNext() {
return min < max;
}
@Override
public boolean tryAdvance(IntConsumer action) {
action.accept(this.next());
return hasNext();
}
@Override
public SpliteratorPrimitive trySplit() {
int middle = (max + min) / 2;
SpliteratorPrimitive nowy = new SpliteratorPrimitive(min, middle);
min = middle;
return nowy;
}
@Override
public long estimateSize() {
return max - min;
}
@Override
public int characteristics() {
return ORDERED | DISTINCT | SIZED | SUBSIZED | NONNULL;
}
}
package p15_parallel_stream.b_spliterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Test1 {
// Stream<Integer> bez spowalniania. Niepotrzebny narzut na boxing
public static void main(String[] args) {
SpliteratorLiczbyNieparzyste spl1 = new SpliteratorLiczbyNieparzyste(10000000);
Stream<Integer> str1 = StreamSupport.stream(spl1, false);
MierzenieCzasu.uruchom(() -> str1.mapToInt(x->x).sum());
SpliteratorLiczbyNieparzyste spl2 = new SpliteratorLiczbyNieparzyste(10000000);
Stream<Integer> str2 = StreamSupport.stream(spl2, true);
MierzenieCzasu.uruchom(() -> str2.mapToInt(x->x).sum());
System.out.println();
}
}
package p15_parallel_stream.b_spliterator;
import java.util.Spliterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Test2 {
// Spliterator sztucznie spowolniony, Stream<Integer>, widać zysk z parallel
public static void main(String[] args) {
Spliterator<Integer> spl1 = new SpliteratorPowolny(10000000);
Stream<Integer> str1 = StreamSupport.stream(spl1, false);
MierzenieCzasu.uruchom(() -> str1.mapToLong(x->x).sum());
Spliterator<Integer> spl2 = new SpliteratorPowolny(10000000);
Stream<Integer> str2 = StreamSupport.stream(spl2, true);
MierzenieCzasu.uruchom(() -> str2.mapToLong(x->x).sum());
}
}
package p15_parallel_stream.b_spliterator;
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;
public class Test3 {
public static void main(String[] args) {
// IntStream bez żadnego boxingnu - działa najszybciej
SpliteratorPrimitive spl1 = new SpliteratorPrimitive(10000000);
IntStream str1 = StreamSupport.intStream(spl1, false);
MierzenieCzasu.uruchom(() -> str1.sum());
SpliteratorPrimitive spl2 = new SpliteratorPrimitive(10000000);
IntStream str2 = StreamSupport.intStream(spl2, true);
MierzenieCzasu.uruchom(() -> str2.sum());
}
}
package p15_parallel_stream.b_spliterator;
import java.util.Spliterator;
import java.util.function.Consumer;
public class TestNieparzyste {
public static void main(String[] args) {
Consumer<Integer> akcja = i -> System.out.print(i + ", ");
SpliteratorLiczbyNieparzyste spl1 = new SpliteratorLiczbyNieparzyste(100);
spl1.forEachRemaining(akcja);
System.out.println();
System.out.println();
Spliterator<Integer> spl2 = new SpliteratorLiczbyNieparzyste(100);
Spliterator<Integer> a = spl2.trySplit();
Spliterator<Integer> b = a.trySplit();
System.out.println("Fragmenty:");
b.forEachRemaining(akcja);
System.out.println();
a.forEachRemaining(akcja);
System.out.println();
spl2.forEachRemaining(akcja);
System.out.println();
System.out.println();
}
}
package p15_parallel_stream.b_spliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class TestStrumienNieparzystych {
public static void main(String[] args) {
Consumer<Integer> akcja = i -> System.out.print(i + ", ");
SpliteratorLiczbyNieparzyste spl1 = new SpliteratorLiczbyNieparzyste(100);
Stream<Integer> str1 = StreamSupport.stream(spl1, false);
str1.forEach(akcja);
System.out.println();
System.out.println();
SpliteratorLiczbyNieparzyste spl2 = new SpliteratorLiczbyNieparzyste(100);
Stream<Integer> str2 = StreamSupport.stream(spl2, true);
str2.forEach(akcja);
System.out.println();
System.out.println();
SpliteratorLiczbyNieparzyste spl3 = new SpliteratorLiczbyNieparzyste(50);
Stream<Integer> str3 = StreamSupport.stream(spl3, false);
int suma3 = str3.mapToInt(x -> x).sum();
System.out.println(suma3);
SpliteratorLiczbyNieparzyste spl4 = new SpliteratorLiczbyNieparzyste(50);
Stream<Integer> str4 = StreamSupport.stream(spl4, true);
int suma4 = str4.mapToInt(x -> x).sum();
System.out.println(suma4);
}
}
package p15_parallel_stream.b_spliterator;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;
public class TestStrumienPrimite {
public static void main(String[] args) {
IntConsumer akcja = i -> System.out.print(i + ", ");
SpliteratorPrimitive spl1 = new SpliteratorPrimitive(100);
IntStream str1 = StreamSupport.intStream(spl1, false);
str1.forEach(akcja);
System.out.println();
}
}
package p16_porownywanie.v1_brak_equals;
public class HaszKody {
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// Jeśli w klasie nie nadpiszemy metody hashCode, to działa domyślna implementacja
// wyliczająca hashcode na podstawie adresu.
// Daje to efekt, że haszkody różnych obiektów są różne.
// Dopóki nie tworzymy miliardów obiektów, to hashcody będą unikalne.
System.out.println("hasz a " + a.hashCode());
System.out.println("hasz r " + r.hashCode());
System.out.println("hasz b " + b.hashCode());
System.out.println("hasz c " + c.hashCode());
}
}
package p16_porownywanie.v1_brak_equals;
public class Osoba {
String imie, nazwisko;
int wiek;
public Osoba(String imie, String nazwisko, int wiek) {
this.imie = imie;
this.nazwisko = nazwisko;
this.wiek = wiek;
}
@Override
public String toString() {
return "Osoba [imie=" + imie + ", nazwisko=" + nazwisko + ", wiek=" + wiek + "]";
}
}
package p16_porownywanie.v1_brak_equals;
import java.util.Objects;
public class Porownywanie {
// Jeśli w klasie nie zdefiniujemy metody equals, to używana jest domyślna implementacja pochodząca z klasy Object,
// która porównuje adresy (działa jak ==).
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// == sprawdza cz yto jest ten sam adres
System.out.println("a == a " + (a == a));
System.out.println("a == r " + (a == r));
System.out.println("a == b " + (a == b));
System.out.println("a == c " + (a == c));
System.out.println();
System.out.println("a.equals(a) " + (a.equals(a)));
System.out.println("a.equals(r) " + (a.equals(r)));
System.out.println("a.equals(b) " + (a.equals(b)));
System.out.println("a.equals(c) " + (a.equals(c)));
System.out.println();
System.out.println("Obj a a " + Objects.equals(a, a));
System.out.println("Obj a r " + Objects.equals(a, r));
System.out.println("Obj a b " + Objects.equals(a, b));
System.out.println("Obj a c " + Objects.equals(a, c));
System.out.println();
}
}
package p16_porownywanie.v1_brak_equals;
import java.util.Set;
import java.util.TreeSet;
public class ZbiorDrzewowy {
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// TreeSet oraz TreeMap w działaniu korzystają z metody compareTo (ewentualnie z komparatora).
// Ten program kończy sie błedem, bo Osoba nie jest Comparable
boolean wynik;
Set<Osoba> zbior = new TreeSet<>();
wynik = zbior.add(a);
System.out.println("a " + wynik);
wynik = zbior.add(r);
System.out.println("r " + wynik);
wynik = zbior.add(b);
System.out.println("b " + wynik);
wynik = zbior.add(c);
System.out.println("c " + wynik);
System.out.println();
System.out.println("Ilośc elementów: " + zbior.size());
for (Osoba osoba : zbior) {
System.out.println(osoba);
}
}
}
package p16_porownywanie.v1_brak_equals;
import java.util.HashSet;
import java.util.Set;
public class ZbiorHaszowy {
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// HashSet oraz HashMap w działaniu korzystają z metod hashCode i equals.
// 1) patrzy jaki jest hashcode i jeśli różny, to traktuje jak różne obiekty
// 2) jeśli hc jest równy, to wtedy porówuje za pomocą equals
boolean wynik; // wynik operacji add: jeśli element został dodany to true, a jeśli nie to false
Set<Osoba> zbior = new HashSet<>();
wynik = zbior.add(a);
System.out.println("a " + wynik);
wynik = zbior.add(r);
System.out.println("r " + wynik);
wynik = zbior.add(b);
System.out.println("b " + wynik);
wynik = zbior.add(c);
System.out.println("c " + wynik);
System.out.println();
System.out.println("Ilość elementów: " + zbior.size());
for (Osoba osoba : zbior) {
System.out.println(osoba);
}
}
}
package p16_porownywanie.v2_bledny_equals;
public class HaszKody {
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// Jeśli w klasie nie nadpiszemy metody hashCode, to działa domyślna implementacja
// wyliczająca hashcode na podstawie adresu.
// Daje to efekt, że haszkody różnych obiektów są różne.
// Dopóki nie tworzymy miliardów obiektów, to hashcody będą unikalne.
System.out.println("hasz a " + a.hashCode());
System.out.println("hasz r " + r.hashCode());
System.out.println("hasz b " + b.hashCode());
System.out.println("hasz c " + c.hashCode());
}
}
package p16_porownywanie.v2_bledny_equals;
import java.util.Objects;
public class Osoba {
String imie, nazwisko;
int wiek;
public Osoba(String imie, String nazwisko, int wiek) {
this.imie = imie;
this.nazwisko = nazwisko;
this.wiek = wiek;
}
@Override
public String toString() {
return "Osoba [imie=" + imie + ", nazwisko=" + nazwisko + ", wiek=" + wiek + "]";
}
// To nie jest "overriding" tylko "overloading".
// Nie nadpisuję "prawdziwej" metody equals pochodzącej z Object, tylko towrzę nową dodatkową metodę odstepną tylko w klasie Osoba.
// Ten equals zadziała tylko jeśli bezpośrednio go wywołamy na obiekcie Osoba,
// ale to nie jest "ten prawdziwy" equals, i Java (np. HashSet) nie będzie brać tej definicji pod uwagę.
public boolean equals(Osoba inna) {
return inna != null
&& Objects.equals(this.imie, inna.imie)
&& Objects.equals(this.nazwisko, inna.nazwisko)
&& this.wiek == inna.wiek;
}
public int hashCode() {
// to jest niewydajne, ale poprawne i muszę to dopisać, aby "oszukać" hashset
return 0;
}
}
package p16_porownywanie.v2_bledny_equals;
import java.util.Objects;
public class Porownywanie {
// Jeśli w klasie nie zdefiniujemy metody equals, to używana jest domyślna implementacja pochodząca z klasy Object,
// która porównuje adresy (działa jak ==).
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// == sprawdza cz yto jest ten sam adres
System.out.println("a == a " + (a == a));
System.out.println("a == r " + (a == r));
System.out.println("a == b " + (a == b));
System.out.println("a == c " + (a == c));
System.out.println();
System.out.println("a.equals(a) " + (a.equals(a)));
System.out.println("a.equals(r) " + (a.equals(r)));
System.out.println("a.equals(b) " + (a.equals(b)));
System.out.println("a.equals(c) " + (a.equals(c)));
System.out.println();
System.out.println("Obj a a " + Objects.equals(a, a));
System.out.println("Obj a r " + Objects.equals(a, r));
System.out.println("Obj a b " + Objects.equals(a, b));
System.out.println("Obj a c " + Objects.equals(a, c));
System.out.println();
}
}
package p16_porownywanie.v2_bledny_equals;
import java.util.Set;
import java.util.TreeSet;
public class ZbiorDrzewowy {
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// TreeSet oraz TreeMap w działaniu korzystają z metody compareTo (ewentualnie z komparatora).
// Ten program kończy sie błedem, bo Osoba nie jest Comparable
boolean wynik;
Set<Osoba> zbior = new TreeSet<>();
wynik = zbior.add(a);
System.out.println("a " + wynik);
wynik = zbior.add(r);
System.out.println("r " + wynik);
wynik = zbior.add(b);
System.out.println("b " + wynik);
wynik = zbior.add(c);
System.out.println("c " + wynik);
System.out.println();
System.out.println("Ilośc elementów: " + zbior.size());
for (Osoba osoba : zbior) {
System.out.println(osoba);
}
}
}
package p16_porownywanie.v2_bledny_equals;
import java.util.HashSet;
import java.util.Set;
public class ZbiorHaszowy {
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// HashSet oraz HashMap w działaniu korzystają z metod hashCode i equals.
boolean wynik; // wynik operacji add: jeśli element został dodany to true, a jeśli nie to false
Set<Osoba> zbior = new HashSet<>();
wynik = zbior.add(a);
System.out.println("a " + wynik);
wynik = zbior.add(r);
System.out.println("r " + wynik);
wynik = zbior.add(b);
System.out.println("b " + wynik);
wynik = zbior.add(c);
System.out.println("c " + wynik);
System.out.println();
System.out.println("Ilośc elementów: " + zbior.size());
for (Osoba osoba : zbior) {
System.out.println(osoba);
}
}
}
package p16_porownywanie.v3_equals;
public class HaszKody {
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// Jeśli w klasie nie nadpiszemy metody hashCode, to działa domyślna implementacja
// wyliczająca hashcode na podstawie adresu.
// Daje to efekt, że haszkody różnych obiektów są różne.
// Dopóki nie tworzymy miliardów obiektów, to hashcody będą unikalne.
System.out.println("hasz a " + a.hashCode());
System.out.println("hasz r " + r.hashCode());
System.out.println("hasz b " + b.hashCode());
System.out.println("hasz c " + c.hashCode());
}
}
package p16_porownywanie.v3_equals;
import java.util.Objects;
public class Osoba {
String imie, nazwisko;
int wiek;
public Osoba(String imie, String nazwisko, int wiek) {
this.imie = imie;
this.nazwisko = nazwisko;
this.wiek = wiek;
}
public String toString() {
return "Osoba [imie=" + imie + ", nazwisko=" + nazwisko + ", wiek=" + wiek + "]";
}
public boolean equals(Object obj) {
if(obj == null || ! (obj instanceof Osoba)) {
return false;
}
Osoba inna = (Osoba)obj;
return Objects.equals(this.imie, inna.imie)
&& Objects.equals(this.nazwisko, inna.nazwisko)
&& this.wiek == inna.wiek;
}
// Formalnym wymaganiem wobec hashCode jest:
// jeśli dwa obiekty są równe (equals), to hashcode'y muszą być równe
// Natomiast dla zwiększenia wydajności jeśli obiekty są różne,
// to z dużym pradopodobieństwem hashcody powinny być różne.
public int hashCode() {
return 0;
}
}
package p16_porownywanie.v3_equals;
import java.util.Objects;
public class Porownywanie {
// Jeśli w klasie nie zdefiniujemy metody equals, to używana jest domyślna implementacja pochodząca z klasy Object,
// która porównuje adresy (działa jak ==).
public static void main(String[] args) {
Osoba a = new Osoba("Ala", "Kowalska", 20);
Osoba r = a;
Osoba b = new Osoba("Ala", "Kowalska", 20);
Osoba c = new Osoba("Ola", "Kowalska", 30);
// == sprawdza cz yto jest ten sam adres
System.out.println("a == a " + (a == a));
System.out.println("a == r " + (a == r));
System.out.println("a == b " + (a == b));
System.out.println("a == c " + (a == c));
System.out.println();
System.out.println("a.equals(a) " + (a.equals(a)));
System.out.println("a.equals(r) " + (a.equals(r)));
System.out.println("a.equals(b) " + (a.equals(b)));
System.out.println("a.equals(c) " + (a.equals(c)));
System.out.println();
System.out.println("Obj a a " + Objects.equals(a, a));
System.out.println("Obj a r " + Objects.equals(a, r));
System.out.println("Obj a b " + Objects.equals(a, b));
System.out.println("Obj a c " + Objects.equals(a, c));
System.out.println();
}
}
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