Skip to content
Snippets Groups Projects
Commit 631835bd authored by dagk's avatar dagk
Browse files

Nye ting uke 9

parent 9a60574d
No related branches found
No related tags found
No related merge requests found
File added
package uke9.lambdastreams;
import java.util.Arrays;
import java.util.Comparator;
// Kode fra https://www.journaldev.com/2763/java-8-functional-interfaces - den var så fin!
import java.util.List;
// Eksempel hentet fra https://www.journaldev.com/2763/java-8-functional-interfaces
// Returnere kvadratet av det største oddetallet under 11 og over 3. Sånt en trenger...
public class NumberTest {
private static int findSquareOfMaxOdd(List<Integer> numbers) {
int max = 0;
for (int i : numbers) {
if (i % 2 != 0 && i > 3 && i < 11 && i > max) {
max = i;
}
}
return max * max;
}
/*
* Poenget her er at en ved å splitte opp if-sjekken ovenfor ved hjelp av streams, og
* egne metoder, så vil en gjøre koden mye mer lesbar.
*/
public static int findSquareOfMaxOdd2(List<Integer> numbers) {
return numbers.stream()
.filter(NumberTest::isOdd) //Predicate is functional interface and
.filter(NumberTest::isGreaterThan3) // we are using lambdas to initialize it
.filter(NumberTest::isLessThan11) // rather than anonymous inner classes
.max(Comparator.naturalOrder())
.map(i -> i * i)
.get(); // Returner den.
}
public static boolean isOdd(int i) {
return i % 2 != 0;
}
public static boolean isGreaterThan3(int i){
return i > 3;
}
public static boolean isLessThan11(int i){
return i < 11;
}
public static void main(String[] args) {
System.out.println(NumberTest.findSquareOfMaxOdd(Arrays.asList(1,2,3,4,5,6,7,8,9,10)));
System.out.println(NumberTest.findSquareOfMaxOdd2(Arrays.asList(1,2,3,4,5,6,7,8,9,10)));
}
}
package uke9.lambdastreams;
import java.util.function.IntPredicate;
import java.util.stream.IntStream;
// Eksempel fra https://www.journaldev.com/2763/java-8-functional-interfaces
public class Prime {
//Tradisjonell måte
private static boolean isPrime(int number) {
if(number < 2) return false;
for(int i=2; i<number; i++){
if(number % i == 0) return false;
}
return true;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
if (isPrime(i)) {
System.out.println(i +" er et primtall");
}
}
// Finnes det andre måter, tro...
}
}
package uke9.lambdastreams;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.String;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class StreamExamples {
public static void main(String[] args) throws IOException {
List<Integer> liste = Arrays.asList(100,21,13,4,5,6,7,8,9,10);
// Fjerne oddetall:
// System.out.print("\nListe av partall:");
// System.out.println(liste.stream()
// .filter(i -> i%2 == 0)
// .toList());
// Summer tall:
// System.out.print("\nSum av tall, med reduce: ");
// System.out.println(liste.stream()
// .reduce(0, (sum, i) -> sum + i));
List<String> people = Arrays.asList("Al", "Skybert", "Farfar",
"Farmor", "Håvard", "Jørn", "Andrea", "Børge");
// // Liste med (unike) lengder av Stringobjekter (sortert i begge rekkefølger):
// System.out.print("\nNavnelengder: ");
// System.out.println(people.stream()
// .map(s -> s.length())
// // .distinct()
// // .sorted()
// .toList());
// Sum av lengder av Stringobjekter:
// System.out.print("\nSum av navnelengder, med mapToInt: ");
// System.out.println(people.stream()
// .mapToInt(s -> s.length())
// .sum());
// Fjerne de første seks elementene i en intstream fra 0 til 10, kvadrere, og telle elementer:
// Endre til sum(), se at peek plutselig viser noe. Lazy er kult!
// System.out.print("\nHopper over noen elementer: ");
// System.out.println(IntStream
// .range(0, 10)
// .map(x -> x*x)
// // .peek(System.out::println)
// .skip(6)
// .count());
// Legge sammen alle tall opp til 200 som går opp i tre og sju
// System.out.print("\nLegge sammen elementer fra 0-200 som går opp i 3 og 7: ");
// System.out.println(IntStream
// .range(0, 200)
// .filter(t -> t%3 == 0)
// .filter(t -> t%7 == 0)
// .sum());
// Lage en kontinuerlig strøm av heltall som deles på et annet tall, og så skrive ut de første 100:
System.out.println("\nBare et skrudd eksempel på hva en kan. Limit er bra, ellers ville den fortsatt...");
IntStream
.range(0,999999999)
// .parallel()
.mapToDouble(n -> Double.valueOf(n)) // Er det samme, men mer tungvinte enn
// .mapToDouble(Double::valueOf)
.map( n -> n/2978)
.peek(System.out::println)
.filter(n -> n % 6532 == 0)
.limit(100)
.forEach(System.out::println);
System.out.println("Ferdig!");
// List<String> folk = Arrays.asList("Al", "Skybert", "Farfarharetlangtnavn", "Farmor", "Håvard", "Jørn", "Andrea", "Børge");
// System.out.println("\nPersoner med navn lenger enn fem tegn, på en fin måte:");
// // Skrive ut alle navn i listen som er mer enn fem tegn, og hvor mange tegn de er.
// folk.stream()
// // .peek(System.out::println)
// .filter(p -> p.length() > 5)
// .map(p -> p+"\t"+p.length())
// .forEach(System.out::println);
// Lage en samling som inneholder alle personene som starter med "A" og lengde over fire.
// System.out.print("\nNavn som starter med F og lengde over 6: ");
// System.out.println(folk.stream()
// .filter(p -> p.startsWith("F"))
// .filter(p -> p.length() > 6)
// .toList());
// System.out.println("\nLese fra fil:");
// // Lese fra fil:
// // Hvis det ikke hadde vært i main kune en brukt getClass.getResource
// // Merk spesialtilfelle. På denne måten må en ikke innkapsle i try. Det må en uten streams.
// System.out.println(new BufferedReader(new InputStreamReader(StreamExamples.class.getResourceAsStream("bands.txt"))).lines()
// // Over: hvis du bruker linjen over i en annen metode enn main, bytt ut klassenavn.class med getClass()
// .filter(p -> p.length() > 8) // Alle bandnavn lenger enn 8 tegn
// .sorted((a, b) -> a.charAt(1) - b.charAt(1)) // sortert på andre bokstav i navnet
// // .peek(System.out::println) // Lurkikk
// .map(n -> n.charAt(1)) // hent bare ut andre bokstav
// // .collect(Collectors.toList())); // Samle til en liste
// .toList()); // Siden Java 17 er dette enklere enn forrige linje.
// // Lese fra en fil på en bestemt plass på maskina:
// String filename = "C:\\Users\\borgeh\\Jobb\\TDT4100\\23test\\tdt4100-students-23\\foreksempel\\src\\main\\"+
// "java\\uke9\\lambdastreams_ferdig\\bands.txt";
// System.out.println("Antall tegn i alle band til sammen: "+Files.lines(Paths.get(filename))
// .mapToInt(b -> b.length()).sum()+"!");
// BinaryOperator:
/*
* Reduce bruker denne. Reduce tar inn to tall og returnerer summen. Det kule er at man
* husker sum til neste gang den kjøres! Første parameter i reduce bestemmer hva sum
* skal være første gang reduce kalles. Neste gang kjøres den nåværende verdien av sum inn.
* På denne måten kan en legge sammen alle verdiene i rekken.
*/
// System.out.println("BinaryOperator: " + IntStream.range(0,100).reduce(0, (sum, i) -> (sum + i)));
// // Eller penere:
// System.out.println("BinaryOperator: " + IntStream.range(0,100).reduce(0, Integer::sum));
// UnaryOperator:
// Interface som tar inn et element, og gjør noe med det. map bruker UnaryOperator!
// UnaryOperator<String> uo = s -> "[" + s + "]"; // Utvider bare strengen foran og bak
// System.out.println("UnaryOperator: " + uo.apply("Verdi"));
// System.out.print("UnaryOperator i stream, ved bruk av map: (kvadrere tall)");
// IntStream.range(1, 10).map(i -> i*i).forEach(d -> System.out.print(" " + d));
}
}
Rolling Stones
Lady Gaga
Jackson Browne
Maroon 5
Meshuggah
Arijit Singh
Elton John
John Mayer
CCR
Einsturzende Neubauten
Eagles
Pink
Lorna Shore
Aerosmith
Adele
Jinjer
Taylor Swift
Faye Wong
Bob Seger
ColdPlay
Boston
The Cars
Cheap Trick
Def Leppard
Ed Sheeran
Dire Straits
Train
Tom Petty
Jack Johnson
Jimmy Buffett
Mumford and Sons
Phil Collins
Rod Stewart
The Script
Elvis
Michael Buble
\ No newline at end of file
package uke9.streams;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
public class Pipeline {
public static void main(String[] args) {
// Fra en Collection lage en liste med Score-objekter. Score blir alle satt til default verdi -1.
Collection<String> ids = Arrays.asList("Ada", "Odd", "Even", "Dina");
Collection<Score> scores = ids.stream().map(name -> new Score(name)).collect(Collectors.toList());
System.out.println(scores);
// Vi kan også lage stream fra en Array på samme måte.
// Vi kan også forenkle skrivemåten for å generere listen.
String[] names = new String[] {"Per", "Ida", "Live", "Pål"};
scores.addAll(Arrays.stream(names).map(Score::new).toList());
System.out.println(scores);
// La oss legge til verdier i Score-objektene:
Random rnd = new Random();
scores.stream().forEach(s -> s.setValue(rnd.nextInt(3))); // forEach tar en Consumer som argument
// Dette kan også gjøres slik:
scores.forEach(s -> s.setValue(rnd.nextInt(3)));
// ... eller slik:
for (Score s : scores) {
s.setValue(rnd.nextInt(3));
}
// En fordel med stream, er at den er designet for å lett koble sammen flere operasjoner
long noWithScore2 = scores.stream().filter(s-> s.getValue() == 2).count();
System.out.println(noWithScore2);
// La oss lage en map fra id til sum av scores
// Mange metoder kan brukes direkte på collections
List<String> nyeNavn = Arrays.asList("Ada", "Bo", "Eva");
nyeNavn.forEach(System.out::println);
// En bruker ikke streams til å slette noe fra input.
nyeNavn.removeIf(n -> n.contains("a"));
}
}
package uke9.streams;
public class Score {
private String id;
private int value;
public Score(String id, int value) {
this.id = id;
this.value = value;
}
public Score(String id) {
this.id = id;
this.value = -1;
}
public String getId() {
return id;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString() {
return "Score{" + "id=" + id + ", value=" + value + '}';
}
}
# Java stream
Javadoc er tilgjengelig under eksamen, så en kan godt venne seg til å bruke den. Oversikt over java.util.stream finner dere her:
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/stream/package-summary.html
En av prinsippene i *funksjonell programmering* er at en ikke modifiserer eksisterende data, men produserer nye data fra eksisterende. Java's stream følger dette prinsippet:
Fra en datakilde (f.eks. en Collection), opprettes en datastrøm av dens elementer, som kan prosesseres element for element.
Prosesseringen kan bestå av flere trinn. Til slutt genreres et resultat ved en såkalt *terminal operasjon*.
```mermaid
flowchart LR
A["Data source"] -.stream().-> B[Stream Creation]
subgraph TB S[Stream]
B --> C[Operation]
C --> D[Operation]
D --> F["Terminal Operation"]
end
F -.-> G[Output]
```
## Hva kan vi gjøre med streams?
Det er to typer operasjoner.
### Mellom-operasjoner
lager ny stream som vi kan fortsette å gjøre nye operasjoner på:
- map(Function<T,R>): bruker en funksjon til å lage ny stream fra T-objekter til R-objekter
- filter(Predicate<T>): ny støm hvor bare elementer som tilfredsstiller predikatet er med
- sorted(), sorted(Comparator<T>): ny støm hvor elementene er sortert.
Alle parametrene her er eksempler på funksjonelle grensesnitt, så en vil ofte angi disse
som *lambda-funksjoner*.
### Terminale operasjoner
avslutter strømmen ofte med et returnert resultat:
- Collect(...) : Returnerer resultat, som f.eks. en liste, Map mm.
- forEach(Consumer<T>): Utfører en operasjon for hvert element i strømmen. **returnerer ingenting**
- reduce(): Returnerer et enkelt resultat, f.eks. sum, ...
- (flere)
I en stream, så utføres ingen prosessering skjer før en har en terminal operasjon, såkalt
"lazy evaluation". Dette betyr at kilden kan være ubegrenset, men at at senere prosesseringssteg
avslutter strømmen.
### Hva er mulige input til en stream
- Collection, arrays,...
- Generatorer
- IO (System.in, fil, ...)
### streams endrer ikke data-kilden
Vi kan sortere elementene i strømmen med sorted, men opprinnelig kilde blir ikke sortert:
- liste.stream().sorted()->toList()
Dette i motsentning til sort() som sorterer "in place":
- liste.sort()
## Hva er en stream ikke?
- En stream ligner på en iterator, men er ikke helt det samme.
- Ikke en datastruktur, men representerer et sett operasjonene som skal utføres på elementene i kilden
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment