Najnowsza wersja Javy – Java 8

Cześć! Cieszę się, że mnie odwiedziłeś/aś. Zanim przejdziesz do artykułu chciałbym zwrocić Ci uwagę na to, że ten artykuł był pisany kilka lat temu (2014-04-18) miej więc proszę na uwadzę że rozwiązania i przemyślenia które tu znajdziesz nie muszą być aktualne. Niemniej jednak zachęcam do przeczytania.

Cześć ;)

Uległem pokusie i ściągnąłem JDK Javy 1.8 :) chciałem potestować, zobaczyć na własne oczy co nowego dodali, pierwszy problem jaki się pojawił – Oracle nie wspiera już Win XP – smutek ogólnie, gdyż ja nadal mam Win XP SP3.. StackOverFlow pomogło to obejść, wystarczy ściągnąć JDK normalnie, 7zipem rozpakować ten plik exe i wrzucić zawartość sobie gdzieś w sensowny folder i uruchomić:

1
FOR /R %%f IN (*.pack) DO "%JAVA_HOME%\bin\unpack200.exe" -r -v "%%f" "%%~pf%%~nf.jar"

oczywiście przed tym warto zmienić zmienną JAVA_HOME na odpowiednią dla tego JDK, czyli na folder gdzie skopiowało się to JDK.

Jeśli masz system Win 7 lub wyżej to zainstaluje się normalnie ;)

Następny problem to zmuszenie Eclipse’a do kompilowania kodu używając nowego JDK, aby to zrobić trzeba uruchomić „Install New Software” w menu Help i po prawej na górze kliknąć Add i tam w location wpisać

1
http://download.eclipse.org/eclipse/updates/4.3-P-builds/

a to co wpiszemy w nazwę nie ma znaczenia ;) gdy klikniecie OK to pojawi się

1
Eclipse Java 8 Support (for Kepler SR2)

zaznaczamy to i instalujemy.

Tworzymy nowy projekt i prawym klikamy na niego, na dole mamy Properties, po lewej stronie odnajmujemy Java Compiler i upewniamy się że wygląda to tak jak tu:

A skoro działa to możemy przejść do szybkiego review ;)

Zacznijmy od strumieni. Nie są to strumienie takie jak otwieramy do, np. plików. Te strumienie pracują na kolekcjach. Każda kolekcja ma teraz metodę stream() oraz parallelStream(), obie zwracają strumień, z tym że druga robi wszystko żeby przetwarzanie było równoległe – ma to swoje plusy i minusy, przetwarzanie, używające parallelStream() będzie szybsze, ale pewnie będzie to realizowane tak że podzieli kolekcję, przemieli jej części osobno i na koniec połączy i warto o tym pamiętać. Strumień udostępnia nam kilkanaście przydatnych funkcji, np:

  • Stream map(Function<? super T,? extends R> mapper)
  • Stream<T> filter(Predicate<? super T> predicate)
  • Stream<T> sorted()
  • Stream<T> sorted(Comparator<? super T> comparator)
  • Stream<T> distinct()
  • void forEach(Consumer<? super T> consumer)
  • Optional<T> reduce(BinaryOperator<T> reducer)

oczywiście, jest ich więcej.

Pierwsza metoda to dobrze znana z innych języków np. Pythona, funkcja map :) czyli wykonanie pewnej czynności dla każdego elementu tablicy. Użyjmy jej może, nie? Ale pierw przygotujmy sobie dane do testów:

1
2
3
4
5
6
7
ArrayList<Double> ints = new ArrayList<Double>();
for(int i=0;i<100000;i++)
  ints.add(i*Math.random());
FileOutputStream fos = new FileOutputStream("s");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(ints);
oos.close();

Czyli sporo liczb typu double ;)
Skoro zrobiliśmy swoisty persist danych, to wczytajmy je:

1
2
3
4
5
ArrayList<Double> numbers;
FileInputStream fos = new FileInputStream("s");
ObjectInputStream oos = new ObjectInputStream(fos);
numbers = (ArrayList<Double>) oos.readObject();
oos.close();

i możemy przystąpić do funkcji map:

1
2
3
4
5
6
7
numbers = (ArrayList<Double>) numbers.stream().map(new Function<Double, Double>() {
@Override
public Double apply(Double arg0) {
             
  return arg0%400;
}
}).collect(Collectors.toList());

lub korzystając z przetwarzania równoległego:

1
2
3
4
5
6
7
numbers = (ArrayList<Double>) numbers.parallelStream().map(new Function<Double, Double>() {
@Override
public Double apply(Double arg0) {
             
  return arg0%400;
}
}).collect(Collectors.toList());

Zmierzyłem czas obu rozwiązań :)
stream – 93ms
parallelStream – 47ms

Java udostępnia wyrażenia lambda, a więc powyższy kod możemy skrócić do:

1
      t = (ArrayList<Double>) numbers.stream().map((d) -> (d%400)).collect(Collectors.toList());

Co raczej nie wypływa na zmianę wydajności a sam interfejs pełni rolę funkcji anonimowych.

Podobnie możemy użyć metody filter:

1
      t = (ArrayList<Double>) numbers.stream().filter(n -> (n>500)).collect(Collectors.toList());

Tutaj używamy interfejsu Predicate, czyli testujemy elementy listy i te które spełniają „zbieramy” metodą collect (była też użyta w przykładzie wcześniej) i zwracamy jako listę, używając do tego Kolektora.

A więc teraz wątek możemy stworzyć np. tak:

1
2
3
4
5
6
7
  new Thread(()->
  {
      int a=6;
      if(a%2==0)
          System.out.println("jestem 2 watkiem ;) ");
     
  }).start();

korzystając dokładnie z tego samego mechanizmu co wcześniej – wyrażeń lambda. Możemy zamienić każdy interfejs który ma dokładnie jedną metodę, dodając mu adnotację:

1
@java.lang.FunctionalInterface

na interfejs którego możemy używać w wyrażeniach lambda.

Na koniec kilka przykładów kodu z Java 8:

1
2
3
4
5
6
7
8
9
10
11
12
  public static void test1(ArrayList<Double> numbers){
      ArrayList<Double> t;
      long start = System.currentTimeMillis();
      t = (ArrayList<Double>) numbers.stream().distinct().filter(n -> (n<30)).collect(Collectors.toList());
      long diff = System.currentTimeMillis()-start;
      System.out.println(diff+"ms");
     
      start = System.currentTimeMillis();
      t = (ArrayList<Double>) numbers.parallelStream().distinct().filter(n -> (n<30)).collect(Collectors.toList());
      diff = System.currentTimeMillis()-start;
      System.out.println(diff+"ms");
  }

Jak sadzicie, co wypisze ten kawałek kodu? Użycie w tym przypadku parallelStream() okaże się zgubne – gdyż distinict() wywala duplikaty co ciężko zrównoleglić a do czasu przeliczania dodaje się wtedy czas przełączania kontekstu, co w efekcie zwiększa czas potrzebny do przeliczenia całości.

Czasy:
Dla stream() – 125ms
Dla parallelStream() – 187ms

Jeśli usuniemy distinict(), czasy przedstawiają się następująca:
stream() – 94ms
parallelStream() – 31ms

Bardzo fajny przykład wykorzystnia możemy tutaj zobaczyć:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Calculator {

  interface IntegerMath {
      int operation(int a, int b);  
  }

  public int operateBinary(int a, int b, IntegerMath op) {
      return op.operation(a, b);
  }

  public static void main(String... args) {
 
      Calculator myApp = new Calculator();
      IntegerMath addition = (a, b) -> a + b;
      IntegerMath subtraction = (a, b) -> a - b;
      System.out.println("40 + 2 = " +
          myApp.operateBinary(40, 2, addition));
      System.out.println("20 - 10 = " +
          myApp.operateBinary(20, 10, subtraction));  
  }
}

jeżeli chcielibyśmy podać jako definicję interfejsu coś więcej niż jedną linijkę to robimy to tak:

1
2
3
IntegerMath soComplicated = (a,b) -> {
      return a/2 + b/2;  
};

Podsumowując, Java 8 to krok w stronę języków typu Python. Warto nad nim chwilkę czasu spędzić :)

Dzięki za wizytę,
Mateusz Mazurek
Mateusz M.

Ostatnie wpisy

Podsumowanie: maj, czerwiec, lipiec i sierpień 2024

Oj daaawnoo mnie tu nie było. Ale wakacje to był czas dużej liczby intensywnych wyjazdów i tak naprawdę, dopiero jakoś… Read More

2 miesiące ago

Podsumowanie: kwiecień 2024

Cześć! Zapraszam na krótkie podsumowanie kwietnia. Wyjazd do Niemiec A dokładniej pod granicę z Francją. Chrześnica miała pierwszą komunię. Po… Read More

6 miesięcy ago

Podsumowanie: luty i marzec 2024

Ostatnio tygodnie były tak bardzo wypełnione, że nie udało mi się napisać nawet krótkiego podsumowanie. Więc dziś zbiorczo podsumuję luty… Read More

7 miesięcy ago

Podsumowanie: styczeń 2024

Zapraszam na krótkie podsumowanie miesiąca. Książki W styczniu przeczytałem "Homo Deus: Historia jutra". Książka łudząco podoba do wcześniejszej książki tego… Read More

9 miesięcy ago

Podsumowanie roku 2023

Cześć! Zapraszam na podsumowanie roku 2023. Książki Zacznijmy od książek. W tym roku cel 35 książek nie został osiągnięty. Niemniej… Read More

10 miesięcy ago

Podsumowanie: grudzień 2023

Zapraszam na krótkie podsumowanie miesiąca. Książki W grudniu skończyłem czytać Mein Kampf. Nudna książka. Ciekawsze fragmenty można by było streścić… Read More

11 miesięcy ago