Java >> Programma Java >  >> Java

Esercitazione API Java 8

In questo articolo, spiegheremo l'API Java 8 attraverso esempi.

1. Introduzione

Java 8 è stato rilasciato il 18 marzo 2014 con diversi miglioramenti. In questo esempio, dimostrerò i seguenti miglioramenti dell'API:

  • Supporta la programmazione funzionale con Lambda Expression, Functional Interface e Stream API
  • Nuova API Java Date
  • Metodo predefinito dell'interfaccia

2. Tecnologie utilizzate

Il codice di esempio in questo articolo è stato compilato ed eseguito utilizzando:

  • Java 8
  • Maven 3.3.9
  • Eclipse di ossigeno
  • Giunto 4.12

3. Progetto Maven

3.1 Dipendenze

Includerò Junit nel pom.xml

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>zheng.jcg.demo</groupId>
	<artifactId>java8-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.3</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

4. Programmazione Funzionale

Java 8 supporta la programmazione funzionale con un'espressione lambda, interfacce funzionali e Stream API. Stream API fornisce metodi che prendono l'interfaccia funzionale come argomento. Il filter il metodo richiede un Predicate discussione. Il map il metodo accetta un Function discussione. ecc.

4.1 Interfaccia funzionale

Un'interfaccia funzionale è un'interfaccia con un solo metodo astratto. Java 8 fornisce @FunctionalInterface annotazione che contrassegna l'interfaccia come interfaccia funzionale. In questo passaggio creerò un GreetingFunction interfaccia che è annotata con @FunctionalInterface . Ha tre metodi:

  • speak() – questo è un metodo astratto e può essere implementato con un'espressione lambda.
  • hello() – questo è un metodo predefinito.
  • bye() – questo è un altro metodo predefinito.

GreetingFunction.java

package com.zheng.demo;

@FunctionalInterface
public interface GreetingFunction {
    void speak(String message);

    default void hello() {
        System.out.println("Hello!");
    }

    default void bye() {
        System.out.println("Bye!");
    }
}

Nota :riga 3:contrassegna questa interfaccia con un @FunctionalInterface annotazione.

Fare clic sul mio altro articolo Tutorial sulla programmazione funzionale Java 8 per i dettagli su come utilizzare le interfacce funzionali predefinite.

4.2 Espressione Lambda

Java 8 ha aggiunto un'espressione lambda (-> ) per implementare un'interfaccia funzionale. In questo passaggio creerò un LambdaDemo classe con tre metodi:

  • implementComparator_anonymous – implementa un java.util.Comparator interfaccia funzionale per confrontare due numeri con una classe anonima.
  • implementComparator_lambda – implementa un java.util.Comparator interfaccia funzionale per confrontare due interi con un'espressione lambda.
  • main() – implementa il GreetingFunction Metodo astratto di 's:speak con un'espressione lambda e richiama i metodi predefiniti:hello () e bye().

LambdaDemo.java

package com.zheng.demo;

import java.util.Comparator;

public class LambdaDemo {
    public static void main(String[] args) {
        GreetingFunction greeting = message -> System.out.println("Hello " + message + "!");
        greeting.hello();
        greeting.speak("Tom");
        greeting.speak("Mary");
        greeting.bye();

        implementComparator_anonymous();
        implementComparator_lambda();
    }

    private static void implementComparator_anonymous() {
        Comparator<Integer> compareInt = new Comparator<Integer>() {

            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };

        System.out.println(compareInt.compare(3, 4));
    }

    private static void implementComparator_lambda() {
        Comparator<Integer> compareInt = (o1, o2) -> {
            return o1.compareTo(o2);
        };

        System.out.println(compareInt.compare(3, 4));
    }

}

Nota :

  • riga 7 e 30 – implementa l'unico metodo astratto con un'espressione lambda.
  • riga 30 – l'implementazione con un'espressione lambda era più compatta dell'implementazione con una classe anonima. Questo perché esiste un solo metodo astratto, quindi il tipo di argomento può essere referenziato dall'unico metodo astratto.

Esegui LambdaDemo e acquisire l'output come segue:

Uscita LambdaDemo

Hello!
Hello Tom!
Hello Mary!
Bye!
-1
-1

4.3 Stream API

Il pacchetto java.util.stream supporta operazioni in stile funzionale. In questo passaggio creerò un StreamTest classe per dimostrare come cercare, filtrare, mappare e ordinare gli elementi.

StreamTest.java

package com.zheng.demo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.junit.Before;
import org.junit.Test;

public class StreamTest {
    private List<String> userNames;

    @Test
    public void test_filter_with_predicate() {
        Predicate<String> startWithA = name -> name.startsWith("a");
        List<String> startWithANames = userNames.stream().filter(startWithA)
                .collect(Collectors.toList());
        assertEquals("aWang", startWithANames.get(0));
    }

    @Test
    public void test_IntStream_sum() {
        int sum = IntStream.of(1, 3, 5, 7, 9).sum();
        assertEquals(25, sum);
    }

    @Test
    public void test_map_with_methodReference() {
        List<String> uppercaseNames = userNames.stream().map(String::toUpperCase)
                .collect(Collectors.toList());
        assertTrue(uppercaseNames.contains("MZHENG"));
        assertTrue(uppercaseNames.contains("AWANG"));
        assertTrue(uppercaseNames.contains("TCHANG"));
    }

    @Test
    public void test_stream_min_max() {
        Comparator<String> comparator = Comparator.comparing(String::length);
        Optional<String> shortestName = userNames.stream().min(comparator);
        assertTrue(shortestName.isPresent());
        assertEquals("aWang", shortestName.get());

        Optional<String> longestName = userNames.stream().max(comparator);
        assertTrue(longestName.isPresent());
        assertEquals("mzheng", longestName.get());

    }

    @Test
    public void test_Stream_foreach() {
        // Internal iteration
        userNames.stream().forEach(System.out::println);
    }

    @Before
    public void setup() {
        userNames = Stream.of("mzheng", "tChang", "aWang").collect(Collectors.toList());
    }

    @Test
    public void test_stream_sort() {
        List<String> sortedNames = userNames.stream().sorted().collect(Collectors.toList());
        assertEquals("aWang", sortedNames.get(0));
        assertEquals("mzheng", sortedNames.get(1));
        assertEquals("tChang", sortedNames.get(2));
    }

}

Note :

  • riga 22 – implementa un Predicate con un'espressione lambda.
  • riga 23:utilizza il filter di Stream metodo.
  • riga 30 – calcola il valore della somma.
  • riga 36:utilizza il map di Stream metodo.
  • riga 46 – trova il valore minimo.
  • riga 50 – trova il valore massimo.
  • riga 59:utilizza il forEach di Stream metodo.
  • riga 69:utilizza il sorted di Stream metodo

Esegui StreamTest come prova Junit e cattura l'output qui.

test mvn -DTest=StreamTest

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.zheng.demo.DateTest
ISO Timestamp: 2021-04-10T07:58:02.297
ISO date: 2021-04-10
Three days date: 2021-04-13T07:58:02.465
Date: 2021-04-05T12:15:00
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.395 sec
Running com.zheng.demo.StreamTest
mzheng
tChang
aWang
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.013 sec

Results :

Tests run: 9, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  15.872 s
[INFO] Finished at: 2021-04-10T07:58:02-05:00
[INFO] ------------------------------------------------------------------------

Fai clic sui miei altri articoli:Stream Map Example e FlatMap Example per i dettagli sulla mappa metodo.

5. Data API

Java 8 fornisce una nuova API Date-Time che include diversi nuovi pacchetti che forniscono un modello completo di data-ora. In questo passaggio creerò un DateTest class per mostrare diverse operazioni di data comuni.

DateTest.java

package com.zheng.demo;

import java.time.LocalDateTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import org.junit.Test;

public class DateTest {

    @Test
    public void test_LocalDateTime_to_formattedString() {
        LocalDateTime now = LocalDateTime.now();
        System.out.println("LocalDateTime now() in ISO_LOCAL_DATE_TIME: "
                + DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(now));
        System.out.println("LocalDateTime now() in ISO_LOCAL_DATE: "
                + DateTimeFormatter.ISO_LOCAL_DATE.format(now));

    }

    @Test
    public void test_ZonedDateTime() {
        ZonedDateTime chicagoTime = ZonedDateTime.now(ZoneId.of("America/Chicago"));

        ZonedDateTime chongqingTime = ZonedDateTime.now(ZoneId.of("Asia/Chongqing"));

        System.out.println("America/Chicago is at: "
                + DateTimeFormatter.ISO_ZONED_DATE_TIME.format(chicagoTime));

        System.out.println("Asia/Chongqing is at: "
                + DateTimeFormatter.ISO_ZONED_DATE_TIME.format(chongqingTime));

        System.out.println("America/Chicago offset:" + chicagoTime.getOffset());
        System.out.println("Asia/Chongqing offset:" + chongqingTime.getOffset());

    }

    @Test
    public void test_formattedString_to_LocalDateTime() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        LocalDateTime d = LocalDateTime.parse("2021-04-05 12:15", formatter);

        System.out.println("Date: " + DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(d));
    }

    @Test
    public void test_add_days_to_LocalDateTime() {
        LocalDateTime newDate = LocalDateTime.now().plus(Period.ofDays(3));
        System.out.println(
                "Three days later: " + DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(newDate));
    }
}

Nota :

  • riga 13 – crea un now oggetto da LocalDatetime.now() e stampa con DateTimeFormatter .
  • riga 23 – crea due ZonedDateTime variabili basate su due ZoneId se ne stampa la data e l'offset del fuso orario.
  • riga 40 – converte un String a LocalDateTime .
  • riga 48 – aggiunge tre giorni alla data e ora corrente.

Esegui DateTest come Junit testa e cattura gli output qui.

mvn test -DTest=DateTest

Running com.zheng.demo.DateTest
Date: 2021-04-05T12:15:00
America/Chicago is at: 2021-04-11T08:29:03.739-05:00[America/Chicago]
Asia/Chongqing is at: 2021-04-11T21:29:03.747+08:00[Asia/Chongqing]
LocalDateTime now() in ISO_LOCAL_DATE_TIME: 2021-04-11T08:29:03.778
LocalDateTime now() in ISO_LOCAL_DATE: 2021-04-11
Three days date: 2021-04-14T08:29:03.78
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.665 sec
Running com.zheng.demo.StreamTest
mzheng
tChang
aWang
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.024 sec

Results :

Tests run: 10, Failures: 0, Errors: 0, Skipped: 0

Fai clic sui miei altri articoli:Data e ora locale, Aggiungi giorni alla data e Confronta i dettagli dell'API data per data.

6. Metodo predefinito

Prima di Java 8, un'interfaccia può avere solo metodi astratti. Java 8 supporta un'interfaccia con metodi predefiniti. Il metodo predefinito ha l'implementazione in modo da non interrompere le classi di implementazione esistenti quando si aggiungono nuovi metodi predefiniti. Il GreetingFunction l'interfaccia al punto 4.1 ha due metodi predefiniti.

Fare clic sul mio altro articolo per i dettagli sull'interfaccia predefinita e su come evitare il problema del diamante causato da eredità multiple.

7. Riepilogo

In questo esempio, ho dimostrato metodi predefiniti, interfacce funzionali, espressione lambda, Stream e Date API. Java 8 mantiene la sua popolarità anche se la sua ultima versione è già 16.

8. Articoli correlati

  • Scarica e installa Java Development Kit (JDK) 8
  • Esercitazione sulle funzionalità di Java 8
  • Esercitazione sull'API Java


Etichetta Java