MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Operații paralele pe array-uri

În JDK 8, clasei Arrays i-au fost adăugate o serie de metode care permit procesarea elementelor unui array în mod paralel. Deși aceste metode nu fac formal parte din Stream API, ele implementează funcționalități similare cu fluxurile paralele:

  • parallelPrefix(): calculează o valoare pe baza elementelor unui array (de exemplu, suma elementelor)
  • parallelSetAll(): setează elementele unui array folosind o expresie lambda
  • parallelSort(): sortează array-ul

Să folosim metoda parallelSetAll() pentru a seta elementele unui array:

import java.util.Arrays;
public class Program {

   public static void main(String[] args) {
       int[] numbers = initializeArray(6);
       for(int i: numbers)
           System.out.println(i);
   }

   public static int[] initializeArray(int size) {
       int[] values = new int[size];
       Arrays.parallelSetAll(values, i -> i * 10);
       return values;
   }
}

În metoda Arrays.parallelSetAll se trec doi parametri: array-ul care va fi modificat și o funcție care setează elementele acestuia. Această funcție parcurge toate elementele și primește indexul elementului curent procesat. Expresia i -> i * 10 înseamnă că la fiecare index din array va fi stocată valoarea i * 10. Rezultatul va fi:

0
10
20
30
40
50

Să vedem un exemplu mai complex cu un obiect Phone:

class Phone{
   private String name;
   private int price;
   
   public Phone(String name, int price){
       this.name = name;
       this.price = price;
   }
   
   public String getName() {
       return name;
   }

   public void setName(String val) {
       this.name = val;
   }

   public int getPrice() {
       return price;
   }

   public void setPrice(int val) {
       this.price = val;
   }
}

Acum să aplicăm metode pe un array de obiecte Phone:

Phone[] phones = new Phone[]{new Phone("iPhone 8", 54000),
   new Phone("Pixel 2", 45000),
   new Phone("Samsung Galaxy S9", 40000),
   new Phone("Nokia 9", 32000)};

Arrays.parallelSetAll(phones, i -> {
   phones[i].setPrice(phones[i].getPrice() - 10000);
   return phones[i];
});

for(Phone p: phones)
   System.out.printf("%s - %d \n", p.getName(), p.getPrice());

Acum, expresia lambda din metoda Arrays.parallelSetAll reprezintă un bloc de cod. Și, deoarece expresia lambda trebuie să returneze un obiect, trebuie să folosim explicit operatorul return.

În această expresie lambda, funcția primește din nou indicii elementelor parcurse, și pe baza acestor indici putem accesa și modifica elementele array-ului. În acest caz specific, are loc o reducere a prețului smartphone-urilor cu 10.000 de unități. În final, vom obține următorul rezultat în consolă:

iPhone 8 - 44000
Pixel 2 - 35000
Samsung Galaxy S9 - 30000
Nokia 9 - 22000

Sortare

Să sortăm un array de numere în mod paralel:

int[] nums = {30, -4, 5, 29, 7, -8};
Arrays.parallelSort(nums);
for(int i: nums)
   System.out.println(i);

Rezultatul va fi:

-8
-4
5
7
29
30

Dacă dorim să sortăm după un alt criteriu, cum ar fi după valoarea absolută sau folosind obiecte mai complexe, putem crea un comparator și îl putem transmite ca al doilea parametru în Arrays.parallelSort(). De exemplu, pentru clasa Phone, putem crea un comparator personalizat:

import java.util.Arrays;
import java.util.Comparator;

public class Program {
   public static void main(String[] args) {
       Phone[] phones = new Phone[]{new Phone("iPhone 8", 54000),
           new Phone("Pixel 2", 45000),
           new Phone("Samsung Galaxy S9", 40000),
           new Phone("Nokia 9", 32000)};
       
       Arrays.parallelSort(phones, new PhoneComparator());

       for(Phone p: phones)
           System.out.println(p.getName());
   }
}

class PhoneComparator implements Comparator<Phone> {
   public int compare(Phone a, Phone b) {
       return a.getName().toUpperCase().compareTo(b.getName().toUpperCase());
   }
}

Metoda parallelPrefix

Metoda parallelPrefix() este utilă atunci când trebuie să obținem un element al array-ului care posedă anumite proprietăți, cum ar fi produsul elementelor:

int[] numbers = {1, 2, 3, 4, 5, 6};
Arrays.parallelPrefix(numbers, (x, y) -> x * y);

for(int i: numbers)
   System.out.println(i);

Rezultatul va fi:

1
2
6
24
120
720

Expresia lambda în Arrays.parallelPrefix reprezintă o funcție binară care primește doi parametri și efectuează o operație asupra lor. Rezultatul operației este stocat și transmis către următorul apel al funcției binare.

← Lecția anterioară Lecția următoare →