Els arrays s'utilitzen per a emmagatzemar múltiples valors en una única variable, enlloc de tenir moltes variables, una per a cada valor. Els valors d'un array estan numerats començant per zero. Per a accedir a un valor d'un array només cal indicar la posició d'aquest element. Aquesta característica és la que dona moltes possibilitats a un array, ja que es pot combinar amb els loops (for i while), i accedir als elements d'un array dintre del loop. D'aquesta forma podem automatitzar un munt de tasques repetitives que utilitzen diferents valors.

En aquest CodeLab utilitzarem els arrays per a una aplicació que genera anuncis, de forma que posarem les dades dels anuncis en arrays, i utitlitzant loops s'aniran recorrent aquestes dades i generant els anuncis en format SVG.

Inicia IntelliJ i crea un nou projecte "Java".

Marca l'opció "Command Line App":

Posa-li de nom CodeLab10

Necessitaràs aquestes imatges. Descarrega-les a la carpeta arrel del projecte, amb els noms indicats.

cam.jpg

console.jpg

cpu.jpg

hdd.jpg

laptop.jpg

pendrive.jpg

printer.jpg

sdcard.jpg

Una botiga d'informàtica vol dur a terme una campanya de màrqueting online basada en descomptes dels seus productes. Han realitzat un disseny gràfic dels anuncis per a mostrar-los en una plataforma de publicitat online.

Aquest és el model de l'anunci que han dissenyat:

A l'anunci apareixen:

El dissenyador gràfic ha realitzat el disseny utilitzant el format vectorial d'imatges SVG. Aquest és el codi de l'anunci:

<svg width="300" height="100">
  <g>
    <image href="file:///C:/Users/gerard/IdeaProjects/AddGenerator/cam.jpg" height="100" width="100" />
    <text style="font-size:14px;fill:#000000;font-family:arial">
      <tspan x="90" y="20">botigainformatica.com</tspan></text>
    <text style="font-size:36px;fill:#000000;font-family:arial">
      <tspan x="90" y="60">Càmeres</tspan></text>
    <rect style="fill:#ff0000;" width="160" height="30" x="70" y="220" transform="matrix(0.7,-0.7,0.7,0.7,0,0)" />
    <text style="font-size:28px;fill:#ffffff;font-family:arial" transform="matrix(0.7,-0.7,0.7,0.7,0,0)">
      <tspan x="115" y="245">10%</tspan></text>
  </g>
</svg>

Fixa't en els elements que hi ha afegit:

Ara la qüestió és que aquest anunci s'ha de repetir per a cadascun dels productes que vol publicitar l'empresa. Ja que l'operació pot ser molt costosa, seria convenient automatitzar aquesta tasca amb un programa.

Desenvoluparem l'aplicació AddGenerator per a poder generar les diferents imatges dels anuncis d'una forma eficient.

El primer pas és analitzar quins són els elements que caldrà canviar en l'anunci original a l'hora de generar la resta d'anuncis.

Aquí tenim dos anuncis, vejem les seves diferències:

Podem veure que el varia d'un anunci a un altre és:

Així doncs ja podem realitzar un primer prototip del programa que ens permiti variar aquestes dades en el codi SVG:

public class Main {

   public static void main(String[] args) {
      String imatge = "cam";
      String nom = "Càmeres";
      int oferta = 10;

       String add = "<svg width=\"300\" height=\"100\">\n" +
               "  <g>\n" +
               "    <image href=\"file:///C:/Users/gerard/IdeaProjects/AddGenerator/" + imatge + ".jpg\" height=\"100\" width=\"100\" />\n" +
               "    <text style=\"font-size:14px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"20\">botigainformatica.com</tspan></text>\n" +
               "    <text style=\"font-size:36px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"60\">" + nom + "</tspan></text>\n" +
               "    <rect style=\"fill:#ff0000;\" width=\"160\" height=\"30\" x=\"70\" y=\"220\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\" />\n" +
               "    <text style=\"font-size:28px;fill:#ffffff;font-family:arial\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\">\n" +
               "      <tspan x=\"115\" y=\"245\">" + oferta + "%</tspan></text>\n" +
               "  </g>\n" +
               "</svg>\n";
       System.out.println(add);
   }
}

Fixa't en que hem utilitzat una variable per a cadascun del valors que varien en un anunci: imatge, nom i oferta. Així, per a generar un nou anunci només hem de canviar el nom d'aquestes variables. De moment no sembla un gran avanç, ja que igualment hauríem d'anar canviat a mà el valor de les variables per a generar els nous anuncis. De seguida veurem com automatitzar-ho. Abans tenim un petit problema, i és que el codi SVG s'imprimeix per consola, però no es guarda en un fitxer (copiar i enganxar a mà el codi en un fitxer no és una opció encertada...).

Per a que el codi SVG s'emmagatzemi en un arxiu en lloc de que es mostri per la consola tenim moltes opcions. Una molt ràpida és redirigir la sortida de la consola a un arxiu usant una eina de l'IDE.

Per a redirigir la sortida de la consola a un arxiu, ves a Run > Edit configurations. A la pestanya Logs trobaràs l'opció Save console output to file, marca-la i especifica el fitxer de sortida adds.html.

Comprova que a l'executar l'aplicació es genera el fitxer adds.html. Obre'l amb el navegador web i comprova que es mostra la imatge SVG correctament.

Prova a canviar els valors de les variables, torna a executar el programa i recarrega (F5) la web al navegador.

El nostre objectiu ara és introduir totes les dades dels productes (imatges, noms i ofertes) i que el programa ens generi d'un sol cop tots els anuncis.

Una aproximació inicial a la solució podria ser repetir el codi que tenim per cada producte, canviant els valors de les variables. Una cosa semblant a aquesta:

public class Main {

   public static void main(String[] args) {
       String imatge = "cam";
       String nom = "Càmeres";
       int oferta = 10;
       System.out.println("<svg width=\"300\" height=\"100\">\n" +
               "  <g>\n" +
               "    <image href=\"file:///C:/Users/gerard/IdeaProjects/AddGenerator/" + imatge + ".jpg\" height=\"100\" width=\"100\" />\n" +
               "    <text style=\"font-size:14px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"20\">botigainformatica.com</tspan></text>\n" +
               "    <text style=\"font-size:36px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"60\">" + nom + "</tspan></text>\n" +
               "    <rect style=\"fill:#ff0000;\" width=\"160\" height=\"30\" x=\"70\" y=\"220\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\" />\n" +
               "    <text style=\"font-size:28px;fill:#ffffff;font-family:arial\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\">\n" +
               "      <tspan x=\"115\" y=\"245\">" + oferta + "%</tspan></text>\n" +
               "  </g>\n" +
               "</svg>\n");

       imatge = "console";
       nom = "Consoles";
       oferta = 15;
       System.out.println("<svg width=\"300\" height=\"100\">\n" +
               "  <g>\n" +
               "    <image href=\"file:///C:/Users/gerard/IdeaProjects/AddGenerator/" + imatge + ".jpg\" height=\"100\" width=\"100\" />\n" +
               "    <text style=\"font-size:14px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"20\">botigainformatica.com</tspan></text>\n" +
               "    <text style=\"font-size:36px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"60\">" + nom + "</tspan></text>\n" +
               "    <rect style=\"fill:#ff0000;\" width=\"160\" height=\"30\" x=\"70\" y=\"220\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\" />\n" +
               "    <text style=\"font-size:28px;fill:#ffffff;font-family:arial\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\">\n" +
               "      <tspan x=\"115\" y=\"245\">" + oferta + "%</tspan></text>\n" +
               "  </g>\n" +
               "</svg>\n");

       imatge = "laptop";
       nom = "Portàtils";
       oferta = 30;
       System.out.println("<svg width=\"300\" height=\"100\">\n" +
               "  <g>\n" +
               "    <image href=\"file:///C:/Users/gerard/IdeaProjects/AddGenerator/" + imatge + ".jpg\" height=\"100\" width=\"100\" />\n" +
               "    <text style=\"font-size:14px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"20\">botigainformatica.com</tspan></text>\n" +
               "    <text style=\"font-size:36px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"60\">" + nom + "</tspan></text>\n" +
               "    <rect style=\"fill:#ff0000;\" width=\"160\" height=\"30\" x=\"70\" y=\"220\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\" />\n" +
               "    <text style=\"font-size:28px;fill:#ffffff;font-family:arial\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\">\n" +
               "      <tspan x=\"115\" y=\"245\">" + oferta + "%</tspan></text>\n" +
               "  </g>\n" +
               "</svg>\n");

       imatge = "pendrive";
       nom = "Pendrives";
       oferta = 25;
       System.out.println("<svg width=\"300\" height=\"100\">\n" +
               "  <g>\n" +
               "    <image href=\"file:///C:/Users/gerard/IdeaProjects/AddGenerator/" + imatge + ".jpg\" height=\"100\" width=\"100\" />\n" +
               "    <text style=\"font-size:14px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"20\">botigainformatica.com</tspan></text>\n" +
               "    <text style=\"font-size:36px;fill:#000000;font-family:arial\">\n" +
               "      <tspan x=\"90\" y=\"60\">" + nom + "</tspan></text>\n" +
               "    <rect style=\"fill:#ff0000;\" width=\"160\" height=\"30\" x=\"70\" y=\"220\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\" />\n" +
               "    <text style=\"font-size:28px;fill:#ffffff;font-family:arial\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\">\n" +
               "      <tspan x=\"115\" y=\"245\">" + oferta + "%</tspan></text>\n" +
               "  </g>\n" +
               "</svg>\n");
   }
}

I així obtenim aquest resultat:

Fixa't que el que estem fent al codi anterior és utilitzar sempre les mateixes variables (String imatge, String nom, int oferta) i anar canviant el seu valor al llarg del programa (cam, console, laptop, pendrive, ...).

És a dir, cadascuna d'aquestes variables, per exemple la variable imatge, només té un valor en un moment donat, i el que anem fent és canviar aquest valor a mesura que avança el programa. Simplificant el codi, podem veure aquest patró:

Enlloc de tenir una variable a la que anem canviant el valor, el que ens permet fer un array és definir múltiples valors per a una variable, i agafar en cada moment el valor que ens interessi.

Per a definir múltiples valors a la variable imatge cal separar-los amb comes i posar-los entre claus.

Cal indicar que la variable imatges ja no és de tipus String, si no de múltiples Strings. Això s'indica amb uns corxets després del tipus String:

Per a agafar el valor que desitjem de la variable imatges haurem d'indicar la posició d'aquest valor. Les posicions dels valors d'un array comencen per 0. Així, per a agafar el primer valor "cam" caldrà indicar la posició 0. El valor "console" té la posició 1, el valor "laptop" la 2 i el valor "pendrive" la posició 3.

Per a indicar quin valor volem agafar d'un array és posa el seu índex entre corxets:

Aquest codi és molt semblant al que havíem fet abans. Ara, enlloc de tenir una variable a la que anem canviant el seu valor i imprimir-la, tenim una variable amb múltiples valors i anem agafant aquests valors per a imprimir-los.

Quina avantatge té aquest codi respecte a l'anterior? Si ens fixem, estem repetint un patró. La instrucció System.out.println sempre és la mateixa i l'únic que varia és la posició del valor que agafem de l'array per a imprimir-lo. Podem transformar aquest patró en un loop.

Si introduïm tots els possibles valors de les imatges, noms i ofertes en arrays, podem fer un loop sobre aquests valors per a generar els anuncis:

public class Main {

   public static void main(String[] args) {
       String[] imatges = {"cam", "console", "laptop", "pendrive"};
       String[] noms = {"Càmeres", "Consoles", "Portàtils", "Pendrives"};
       int[] ofertes = {10, 15, 30, 5};

       for (int i = 0; i < 4; i++) {
           System.out.println("<svg width=\"300\" height=\"100\">\n" +
                   "  <g>\n" +
                   "    <image href=\"file:///C:/Users/gerard/IdeaProjects/AddGenerator/" + imatges[i] + ".jpg\" height=\"100\" width=\"100\" />\n" +
                   "    <text style=\"font-size:14px;fill:#000000;font-family:arial\">\n" +
                   "      <tspan x=\"90\" y=\"20\">botigainformatica.com</tspan></text>\n" +
                   "    <text style=\"font-size:36px;fill:#000000;font-family:arial\">\n" +
                   "      <tspan x=\"90\" y=\"60\">" + noms[i] + "</tspan></text>\n" +
                   "    <rect style=\"fill:#ff0000;\" width=\"160\" height=\"30\" x=\"70\" y=\"220\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\" />\n" +
                   "    <text style=\"font-size:28px;fill:#ffffff;font-family:arial\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\">\n" +
                   "      <tspan x=\"115\" y=\"245\">" + ofertes[i] + "%</tspan></text>\n" +
                   "  </g>\n" +
                   "</svg>\n");
       }
   }
}

El resultat és el mateix que el que havíem aconseguit abans, però ara el codi és més breu i ens permet modificacions més ràpidament.

És a dir si ara volem afegir la resta de productes, només cal afegir els seus valors als arrays, i d'aquesta forma el loop anirà agafant tots aquests valors automàticament.

String[] imatges = {"cam", "console", "laptop", "pendrive", "cpu", "hdd", "printer", "sdcard"};
String[] noms = {"Càmeres", "Consoles", "Portàtils", "Pendrives", "CPUS", "Discs durs", "Impressores", "Tarjes SD"};
int[] ofertes = {10, 15, 30, 5, 20, 25, 35, 50};

Només caldrà canviar el valor fins al qual ha d'arribar la variable i. Els valor de la variable i hauran de recòrrer tots els elements de l'array. Com als arrays hi ha 8 elements, la variable i haurà d'anar des del valor 0 al valor 7.

for (int i = 0; i < 8; i++) {
  
}

És molt comú realitzar aquest recorregut per els elements d'un array fent que la variable i del loop vagi des de 0 fins a ú menys que el nombre d'elements, i utilitzant aquesta variable per a indicar quin valor de l'array s'agafa en cada iteració del loop.

Aquest 8 que veiem en el for sempre serà el nombre d'elements que tinguem a l'array, i la variable i sempre anirà desde 0 (la posició del primer element) fins a ú menys que el nombre d'elements (la posició de l'últim element, 7 en aquest cas).

Podem substituir el nombre 8 per la variable imatges.length que ens diu, precisament, el nombre d'elements de l'array.

Finalment el codi queda així:

public class Main {

   public static void main(String[] args) {
       String[] imatges = {"cam", "console", "laptop", "pendrive", "cpu", "hdd", "printer", "sdcard"};
      String[] noms = {"Càmeres", "Consoles", "Portàtils", "Pendrives", "CPUS", "Discs durs", "Impressores", "Tarjes SD"};
      int[] ofertes = {10, 15, 30, 5, 20, 25, 35, 50};

       for (int i = 0; i < imatges.length; i++) {
           System.out.println("<svg width=\"300\" height=\"100\">\n" +
                   "  <g>\n" +
                   "    <image href=\"file:///C:/Users/gerard/IdeaProjects/AddGenerator/" + imatges[i] + ".jpg\" height=\"100\" width=\"100\" />\n" +
                   "    <text style=\"font-size:14px;fill:#000000;font-family:arial\">\n" +
                   "      <tspan x=\"90\" y=\"20\">botigainformatica.com</tspan></text>\n" +
                   "    <text style=\"font-size:36px;fill:#000000;font-family:arial\">\n" +
                   "      <tspan x=\"90\" y=\"60\">" + noms[i] + "</tspan></text>\n" +
                   "    <rect style=\"fill:#ff0000;\" width=\"160\" height=\"30\" x=\"70\" y=\"220\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\" />\n" +
                   "    <text style=\"font-size:28px;fill:#ffffff;font-family:arial\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\">\n" +
                   "      <tspan x=\"115\" y=\"245\">" + ofertes[i] + "%</tspan></text>\n" +
                   "  </g>\n" +
                   "</svg>\n");
       }
   }
}

I d'aquesta forma generem d'una sola execució totes les posibles imatges per a la campanya d'anuncis online:

Aquesta forma d'automatitzar el recorregut per els valors dels arrays utilitzant loops, ens permet una gran versatilitat a l'hora d'adaptar el nostre codi a noves situacions.

Per exemple, imagina que ara volem provar diversos colors per a l'oferta per tal d'anar provant-los amb la finalitat de veure quin color és el que més atrau als nostres clients:

public class Main {

   public static void main(String[] args) {
       String[] colors = {"#ff0000","#00ff00","#0000ff","#ffff00","#ff00ff","#00ffff"};
       String[] imatges = {"cam", "console", "laptop", "pendrive", "cpu", "hdd", "printer", "sdcard"};
      String[] noms = {"Càmeres", "Consoles", "Portàtils", "Pendrives", "CPUS", "Discs durs", "Impressores", "Tarjes SD"};
      int[] ofertes = {10, 15, 30, 5, 20, 25, 35, 50};

       for (int j = 0; j < colors.length; j++) {
           for (int i = 0; i < imatges.length; i++) {
               System.out.println("<svg width=\"300\" height=\"100\">\n" +
                       "  <g>\n" +
                       "    <image href=\"file:///C:/Users/gerard/IdeaProjects/AddGenerator/" + imatges[i] + ".jpg\" height=\"100\" width=\"100\" />\n" +
                       "    <text style=\"font-size:14px;fill:#000000;font-family:arial\">\n" +
                       "      <tspan x=\"90\" y=\"20\">botigainformatica.com</tspan></text>\n" +
                       "    <text style=\"font-size:36px;fill:#000000;font-family:arial\">\n" +
                       "      <tspan x=\"90\" y=\"60\">" + noms[i] + "</tspan></text>\n" +
                       "    <rect style=\"fill:"+ colors[j] + ";\" width=\"160\" height=\"30\" x=\"70\" y=\"220\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\" />\n" +
                       "    <text style=\"font-size:28px;fill:#ffffff;font-family:arial\" transform=\"matrix(0.7,-0.7,0.7,0.7,0,0)\">\n" +
                       "      <tspan x=\"115\" y=\"245\">" + ofertes[i] + "%</tspan></text>\n" +
                       "  </g>\n" +
                       "</svg>\n");
           }
       }
   }
}

Només afegint els possibles colors en un array, i fent un loop sobre els valors d'aquest array, aconseguim generar tots els possibles anuncis. Només amb dues línies de codi. Torna enrere i pensa quantes línies de codi hauríem necessitat per a generar tots aquests anuncis sense utilitzar arrays i loops...