Java Syncronized: Come si usa esempio

Java Syncronized: Cos’è

Ad ogni oggetto (o anche ad un pezzo di codice) si può associare un semaforo (un lock). Ogni semaforo ha due operazioni: Get e Release. Quando un thread accede ad una zona critica tenta di prendere possesso del semaforo (Get); se non ci riesce verrà messo a dormire e ci ritenterà fino a quando un altro thread rilascerà (Release) tale semaforo.
Questi “semafori” in java vengono introdotti con la parola chiave “syncronized“. Si possono sincronizzare sia classi che metodi.
Quando un thread vuole accedere ad un metodo/blocco synchronized, deve acquisire il lock dell’oggetto (impedendo così l’accesso ad ogni altro thread).  Il lock viene automaticamente rilasciato quando il thread esce dal metodo/blocco synchronized(o se viene interrotto da un’eccezione).
Un thread che non riesce ad acquisire un lock rimane sospeso sulla richiesta della risorsa fino a che il lock non è disponibile. Ad ogni oggetto viene assegnato un solo lock: due thread non possono accedere contemporaneamente a due metodi/blocchi synchronized diversi di uno stesso oggetto.Tuttavia altri thread sono liberi di accedere a metodi/blocchi non synchronized associati allo stesso oggetto.

Java Syncronized: Esempio

Continua a leggere

Java HashMap – Esempio Collisione

Per poter usare correttamente l’HashMap bisogna implementare correttamente l’override delle funzioni hashcode() e equals() altrimenti si incorre nel problema delle collisioni, ossia per due chiavi diverse che hanno lo stesso hashcode,e quindi andranno nella stessa locazione,  non ci sarà modo di capire se si devono essere sovrascritti o aggiunti in quella locazione.

Per risolvere questo problema si deve fare l’override di haschcode (in modo da ridurre al minimo la possibilità che due chiavi diverse abbiano lo stesso hash) e anche di equals.In questo modo quando due chiavi diverse (due chiavi associati a due valori diversi) hanno lo stesso hashcode  viene utilizzata la  funzione equals per capire se è la stessa chiave o no. Se è la stessa chiave, viene aggiornata la coppia chiave-valore (ricordiamoci che nella locazione vengono inserite le coppie chiavi-valori), altrimenti viene aggiunta.

Vediamo un esempio che mostra un caso di hashmap con collisione risolto tramite l’equals:

Esempio:

Definiamo una classe Persona in cui l override di hashcode è fatto in modo tale che ritorni l’id.


package example.hashmap;

public class Persona {
private String nome;
private int id;

public Persona(String nome, int id) {
this.nome = nome;
this.id = id;
}

public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}

@Override
public int hashCode() {

System.out.println("chiamato hashCode per ="+ id+"."+nome);
return id;
}

@Override
public boolean equals(Object obj) {
System.out.println("called equals on ="+ id+"."+nome + " to compare with = "+ ((Persona)obj).getId() + "."+ ((Persona)obj).getNome());

if( ((Persona)obj).getId() == id && ((Persona)obj).getNome().equals(nome) )
return true;
return false;
}
}

Nel main, vengono create 3 chiavi, di cui due i (p1 e p3)  hanno lo stesso id (1), quindi lo stesso hashcode, e inserite dentro una mappa.


package example.hashmap;

import java.util.HashMap;

public class ProvaMap {

public static void main(String[] args) {

// //ESEMPIO COLLISIONE
Persona p1 = new Persona("mario",1);
Persona p2 = new Persona("gino",2);
Persona p3 = new Persona("flavio",1);// viene messo lo stesso id di p1, l hashcode per
// come definito ritorna l id.

HashMap<Persona, String> mappa = new HashMap<Persona, String>();

mappa.put(p1, "ONE");
mappa.put(p2, "TWO");
mappa.put(p3, "THREE");

 

Persona p1Bis = new Persona("mario",1);

String value = mappa.get(p1Bis);
System.out.println(" value: "+ value);

//nell output si vede che chiama l hashcode per "mario" che da 1,
//// ma nella posizione 1 è memorizzato anche "flavio" quindi
//// chiama anche equals per capire quale chiave è corretta

}

}

L’output sarà:

HashMap esempio collisione

Quando inserisco la p3 nella mappa, nell’output si nota  la chiamata al metodo equals per capire se la chiave già presente nella locazione con indirizzo 1 (ossia p1, “1.mario”) è uguale o no alla p3 (“1.flavio”).  Equals dice che sono diversi quindi avremo che nella locazione 1 ci sono due coppie chiave-valore (p1-ONE e p3-THREE)

Java e Excel – Lettura File

Per poter lavorare con un foglio excel con il progetto Apache POI è perfetto. Completo e semplice da capire.
Per poterlo utilizzare è sufficiente aggiungere le seguenti dependency nel pom.xml:


<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>


La lettura di un file Excel è abbastanza semplice e si compone dei seguenti passaggi:

  1. Creare una istanza di workboot dal foglio Excel
  2. Prendere lo sheet desiderato
  3. Incrementare il numero di riga
  4. iterare tutte le celle di una riga
  5. ripetere il punto 3 e 4 fino a quando tutti i dati vengono letti

Traducendo i passaggi in codice si ha:


package com.proxima.util;

import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadExcel {

public static void main(String[] args)
{
try
{
FileInputStream file = new FileInputStream(new File("esempio.xlsx"));

//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);

//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);

//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
//For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();

while (cellIterator.hasNext())
{
Cell cell = cellIterator.next();
//Check the cell type and format accordingly
switch (cell.getCellType())
{
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "t");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "t");
break;
}
}
System.out.println("");
}
file.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}

}

Java 8: Espressioni Lambda in 5 minuti

Java 8 Lambda: cosa sono

Le espressioni Lambda costituiscono la principale novità per il linguaggio di programmazione Java 8. Esse sono collegate al concetto di funzione anonima (funzione non classe anonima), ossia una funzione che ha un corpo ma non un nome, definita nel punto in cui viene utilizzata. La loro sintassi è qualcosa di simile:

(arg1, arg2) -> {body}

Java 8 Lambda: Esempi
// espressione che prende in input due interi e restituisce la somma
(int x, int y) -> x + y

// espressione che prende in input una stringa e restituisce la sua lunghezza
s -> s.length()

// espressione senza argomenti che restituisce il valore 50
() -> 50

// espressione che prende in input una stringa e non restituisce nulla
(String s) -> { System.out.println(“Benvenuto “);
System.out.println(s); }

//ERRORE
(int x, 5) -> x + y
In un’espressione lambda o nessuno dei tipi dei parametri è dichiarato oppure lo devono essere tutti. Se c’è solamente un parametro, le parentesi tonde possono essere omesse,
Vengono chiamate interfacce funzionali (functional interface) delle interfacce con un solo metodo astratto. Sono generalmente marcate con l’annotazione @FunctionalInterface, anche se non è obbligatorio. Le lambda sono usate con le funcional interface.

Esempio:
// Anonymous Runnable
Runnable r1 = new Runnable(){

@Override
public void run(){
System.out.println(“Hello world old style!”);
}
};

// Lambda Runnable
Runnable r2 = () -> System.out.println(“Hello world with Lambda!”);

E’ abbastanza evidente come con l’uso delle lambda abbiamo ridotto un pezzo di codice da 5 linee a 1 soltanto.
Esempio:

//Prima:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(“Sintassi arcinota!”);
}
});

//Dopo:
button.addActionListener( (e) -> {
System.out.println(“Nuova sintassi!”);
});

Ricapitolando, l’espressione lambda è una sintassi più semplice e leggibile per definire-creare un’istanza di una classe anonima che implementa un’interfaccia con un solo metodo astratto. Esse si concentrano solamente sulla definizione dell’unico metodo astratto dell’interfaccia.

Usando le espressioni lambda si può utilizzare un altro strumento aggiunto con java8, i reference method. E’ una nuova sintassi per poter invocare un metodo o un costruttore già esistente.
Esempio:
class Numbers {
public static boolean isMoreThanFifty(int n1, int n2) {
return (n1 + n2) > 50;
}

}

public static void main(String[] args) {

// Using an anonymous class
BiPredicate<Integer, Integer> a = new BiPredicate<Integer, Integer>() {
public boolean test(Integer i1, Integer i2) {
return Numbers.isMoreThanFifty(i1, i2);
}
};

// Using a lambda expression
BiPredicate<Integer, Integer> b = Numbers::isMoreThanFifty;

// Using a method reference
BiPredicate<Integer, Integer> c = (i1, i2) -> Numbers.isMoreThanFifty(i1, i2);

//i tre oggetti sono equivalenti
System.out.println(a.test(2, 3));
System.out.println(b.test(2, 3));
System.out.println(c.test(2, 3));

}
da notare che il metodo isMoreThanFifty ha bisogno di due parametri in input. Con il method reference non sono stati menzionati. Questo perche quando invochiamo il metodo test sull’istanza a.test(10,15), i parametri in input vengono passati in automatico al metodo Numbers.isMoreThanFifty(10, 15).

In generale la sintassi di un method reference può essere una delle seguenti:

NomeClasse::metodoIstanza // Il primo parametro è l’oggetto su cui è invocato
// il metodo e gli eventuali altri parametri sono
// passati al metodo
NomeClasse::metodoStatico // Tutti i parametri sono passati al metodo
oggetto::metodoIstanza // Tutti i parametri sono passati al metodo
E’ possibile anche invocare il costruttore con la stessa sintassi:
String:new

Esempio:

BiPredicate<String,String> eqstr = (s1,s2) -> s1.equals(s2);

con lambda diventa

BiPredicate<String,String> eqstr = String::equals;

eqstr.test(tmp, tmp2);

ossia il metodo equals sarà chiamato su tmp:

tmp.equals(tmp2);

Check esistenza file

        String pathFile = “/photos/profile/photoProfile.png”;
        File file = new File(pathFile);

         boolean existsFile = file.isFile();
        if (!existsFile) {
          System.out.println(“foto profilo non esistente”);
        }
        else
          System.out.println(“foto profilo  esistente”);

Java StringTokenizer Example

La classe StringTokenizer è usata per dividere una stringa in varie sottostringhe, delimitate da un carattere speciale.

1° Esempio – Lettura Stringa

Divisione di una stringa con il carattere speciale blank e la virgola.

StringTokenizer.java
package com;

import java.util.StringTokenizer;

public class StringTokenizerTest {

 /**
  * @param args
  */
 public static void main(String[] args) {
  String str = "prova1 prova2 , test1 test2, prova3 test3";
  StringTokenizer st = new StringTokenizer(str);
 
  System.out.println("---- Split by space ------");
  while (st.hasMoreElements()) {
   System.out.println(st.nextElement());
  }
 
  System.out.println("---- Split by comma ',' ------");
  StringTokenizer st2 = new StringTokenizer(str, ",");
 
  while (st2.hasMoreElements()) {
   System.out.println(st2.nextElement());
  }

 }

}


output:
2 Esempio: Lettura File CVS
Le stringhe da splittare sono lette da un file cvs.
friends.cvs
prova| prova1 | prova2| prova3
test | test1  | test2 | test3
CaricaFile.java
package com;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;

public class CaricaFile {

 public static void caricaUsers() throws IOException {
  BufferedReader reader = new BufferedReader(new FileReader(
    "D:\friends.txt"));
  String line = reader.readLine();
  while (line != null) {

  StringTokenizer stRecord = new StringTokenizer(line, "|");
   while (stRecord.hasMoreTokens()) {
    String record = stRecord.nextToken();
    System.out.print(record + "  ");
   }
   System.out.println("");
   line = reader.readLine();
  }
 }

 public static void main(String[] args) throws FileNotFoundException,
   IOException {
  caricaUsers();
 }
}


Output:

Java Reflection Esempio

Copiare due classi diverse ma con gli stessi campi tramite la reflection

Bean 

A.java

package com;

import java.lang.reflect.Field;

public class A {
private String name;

private long punteggio;

public long getPunteggio() {
return punteggio;
}

public void setPunteggio(long punteggio) {
this.punteggio = punteggio;
}

public String getName() {
return name;
}

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

}

B.java

package com;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class B {
private String name;

private long punteggio;

public long getPunteggio() {
return punteggio;
}

public void setPunteggio(long punteggio) {
this.punteggio = punteggio;
}

public String getName() {
return name;
}

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

public void copy(Object obj) {
try {

Method[] methods = obj.getClass().getMethods();

for (int i = 0; i < methods.length; i++) {
String methodName = methods[i].getName();
try{
if(methodName.startsWith(“get”)){
this.getClass().getMethod(methodName.replaceFirst(“get”, “set”) , methods[i].getReturnType() ).invoke(this, methods[i].invoke(obj, null));
}else if(methodName.startsWith(“is”) ){
this.getClass().getMethod(methodName.replaceFirst(“is”, “set”) ,  methods[i].getReturnType()  ).invoke(this, methods[i].invoke(obj, null));
}

}catch (NoSuchMethodException e) {
// TODO: handle exception
}catch (IllegalArgumentException e) {
// TODO: handle exception
}

}

} catch (Exception ex) {
ex.printStackTrace();
}
}

}


Classe per il test:
TestReflection.java
package com;
public class TestReflection {
public static void main(String[] args) {
A obj1 = new A();
obj1.setName(“hello world”);
A obj2 = new A();
obj2.copy(obj1);
System.out.println(“name obj copy with reflection:”+obj2.getName());
}
}
Esecuzione
lanciando il main si ottiene una copia identica dell’istanza obj1:

Read Write File With InputStream OutputStream Java

Le istruzioni che leggono  il  file con InputStream sono:

InputStream inputStream = new FileInputStream(“c:/myFile.txt”);
inputStream.read(bytes);

Per scrivere su un file con OutputStream:

OutputStream outputStream = new FileOutputStream(new File(“c:/myFileNew.txt”));
outputStream.write(bytes, off, len);// scrive un array di byte di  lunghezza len a partire da posizione off

Esempio completo:

package com;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class InputStreamToFile {
    public static void main(String[] args) {

InputStream inputStream = null;
OutputStream outputStream = null;

try {
inputStream = new FileInputStream(“c:/myFile.txt”);

// write the inputStream to a FileOutputStream
outputStream = new FileOutputStream(new File(“c:/myFileNew.txt”));

int read = 0;
byte[] bytes = new byte[1024];

while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}

System.out.println(“Done!”);

} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
// outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}

}
}
    }
}

How To Create New File

import java.io.*;

public class CreateFile{
  public static void main(String[] args) throws IOException{
  File f;
  f=new File(“myfile.txt”);
  if(!f.exists()){
  f.createNewFile();
  System.out.println(“New file “myfile.txt” has been created
  to the current directory”);
  }
  }
}

How To Write To File In Java with BufferedWriter

BufferedWriter è una classe per gestire uno  Stream dati di tipo carattere.

package com;
 
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
 
public class WriteToFileExample {
 public static void main(String[] args) {
  try {
 
   String content = "bla bla bla";
 
   File file = new File("/prova/filename.txt");
 
   // if file doesnt exists, then create it
   if (!file.exists()) {
    file.createNewFile();
   }
 
   FileWriter fw = new FileWriter(file.getAbsoluteFile());
   BufferedWriter bw = new BufferedWriter(fw);
   bw.write(content);
   bw.close();
 
   System.out.println("Done");
 
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}