Java >> Java tutorial >  >> Tag >> return

Sådan returneres flere værdier fra en Java-metode

1. Oversigt

I denne øvelse lærer vi forskellige måder at returnere flere værdier fra en Java-metode på.

Først returnerer vi arrays og samlinger. Derefter viser vi, hvordan man bruger containerklasser til komplekse data og lærer, hvordan man opretter generiske tuple-klasser.

Til sidst vil vi se eksempler på, hvordan man bruger tredjepartsbiblioteker til at returnere flere værdier.

2. Brug af arrays

Arrays kan bruges til at returnere både primitive datatyper og referencedatatyper .

For eksempel følgende getCoordinates metode returnerer en matrix på to dobbelt værdier:

double[] getCoordinatesDoubleArray() {
  
    double[] coordinates = new double[2];

    coordinates[0] = 10;
    coordinates[1] = 12.5;
  
    return coordinates;
}

Hvis vi ønsker at returnere en matrix af forskellige referencetyper, kan vi bruge en fælles overordnet type som matrixens type :

Number[] getCoordinatesNumberArray() {
  
    Number[] coordinates = new Number[2];

    coordinates[0] = 10;   // Integer
    coordinates[1] = 12.5; // Double
  
    return coordinates;
}

Her har vi defineret koordinaterne matrix af typen Antal fordi det er den fælles klasse mellem Heltal og Dobbelt elementer.

3. Brug af samlinger

Med generiske Java-samlinger kan vi returnere flere værdier af en fælles type .

Samlingsrammen har et bredt spektrum af klasser og grænseflader. I dette afsnit vil vi dog begrænse vores diskussion til listen og Kort grænseflader.

3.1. Returner værdier af lignende type i en liste

Til at starte med, lad os omskrive det forrige array-eksempel ved hjælp af List :

List<Number> getCoordinatesList() {
  
    List<Number> coordinates = new ArrayList<>();
  
    coordinates.add(10);  // Integer
    coordinates.add(12.5);  // Double
  
    return coordinates;
}

Ligesom Nummer[] , Liste samling indeholder en sekvens af blandede elementer, alle af den samme almindelige type.

3.2. Returnering af navngivne værdier på et kort

Hvis vi gerne vil navngive hver post i vores samling, et kort kan bruges i stedet:

Map<String, Number> getCoordinatesMap() {
  
    Map<String, Number> coordinates = new HashMap<>();
  
    coordinates.put("longitude", 10);
    coordinates.put("latitude", 12.5);
  
    return coordinates;
}

Brugere af getCoordinatesMap metode kan bruge "længdegrad" eller "breddegrad" tasterne med Map#get metode til at hente den tilsvarende værdi.

4. Brug af containerklasser

I modsætning til arrays og samlinger kan beholderklasser (POJO'er) ombryde flere felter med forskellige datatyper .

For eksempel følgende Koordinater klasse har to forskellige datatyper, dobbelt og streng :

public class Coordinates {
  
    private double longitude;
    private double latitude;
    private String placeName;
  
    public Coordinates(double longitude, double latitude, String placeName) {
  
        this.longitude = longitude;
        this.latitude = latitude;
        this.placeName = placeName;
    }
  
    // getters and setters
}

Brug af containerklasser som Koordinater gør det muligt for os at modellere komplekse datatyper med meningsfulde navne .

Det næste trin er at instansiere og returnere en forekomst af Koordinater :

Coordinates getCoordinates() {
  
    double longitude = 10;
    double latitude = 12.5;
    String placeName = "home";
  
    return new Coordinates(longitude, latitude, placeName);
}

Vi skal bemærke, at det anbefales, at vi laver dataklasser som Koordinater uforanderlig . Ved at gøre det skaber vi enkle, trådsikre objekter, der kan deles.

5. Brug af Tuples

Ligesom containere opbevarer tupler marker af forskellige typer. De adskiller sig dog ved, at de ikke er applikationsspecifikke .

De er specialiserede, når vi bruger dem til at beskrive, hvilke typer vi ønsker, at de skal håndtere, men er generelle formål med et vist antal værdier. Det betyder, at vi ikke behøver at skrive tilpasset kode for at have dem, og vi kan bruge et bibliotek eller oprette en fælles enkelt implementering.

En tuple kan bestå af et vilkårligt antal felter og kaldes ofte Tupel n, hvor n er antallet af felter. For eksempel er Tuple2 en tofelts tupel, Tuple3 er en trefelts tupel og så videre.

For at demonstrere vigtigheden af ​​tupler, lad os overveje følgende eksempel. Antag, at vi ønsker at finde afstanden mellem en Koordinater punkt og alle andre punkter inde i en Liste . Derefter skal vi returnere det fjerneste koordinatobjekt sammen med afstanden.

Lad os først oprette en generisk to-felts tuple:

public class Tuple2<K, V> {

    private K first;
    private V second;
  
    public Tuple2(K first, V second){
        this.first = first;
        this.second = second;
    }

    // getters and setters
}

Lad os derefter implementere vores logik og bruge en Tuple2 forekomst for at pakke resultaterne:

Tuple2<Coordinates, Double> getMostDistantPoint(List<Coordinates> coordinatesList, 
                                                       Coordinates target) {

    return coordinatesList.stream()
      .map(coor -> new Tuple2<>(coor, coor.calculateDistance(target)))
      .max((d1, d2) -> Double.compare(d1.getSecond(), d2.getSecond())) // compare distances
      .get();
}

Brug af Tuple2 i det foregående eksempel har reddet os fra at oprette en separat containerklasse til engangsbrug med denne særlige metode .

Ligesom containere bør tupler være uforanderlige . På grund af deres generelle karakter bør vi desuden bruge tuples internt i stedet for som en del af vores offentlige API .

6. Tredjepartsbiblioteker

Nogle tredjepartsbiblioteker har implementeret et uforanderligt par eller Tredobbelt type. Apache Commons Lang og javatuples er gode eksempler. Når vi har disse biblioteker som afhængigheder i vores applikation, kan vi direkte bruge Pair eller Tredobbelt typer leveret af bibliotekerne i stedet for at skabe dem af os selv.

Lad os se på et eksempel, der bruger Apache Commons Lang til at returnere et par eller en Triple objekt.

Inden vi går videre, lad os tilføje commons-lang3 afhængighed i vores pom.xml:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

6.1. ImmutablePair fra Apache Commons Lang

ImmutablePair type fra Apache Commons Lang er præcis, hvad vi ønsker:en uforanderlig type, hvis brug er ligetil.

Den indeholder to felter:venstre og højre . Lad os se, hvordan du laver vores getMostDistantPoint metode returnerer et objekt af ImmutablePair type:

ImmutablePair<Coordinates, Double> getMostDistantPoint(
  List<Coordinates> coordinatesList, Coordinates target) {
    return coordinatesList.stream()
      .map(coordinates -> ImmutablePair.of(coordinates, coordinates.calculateDistance(target)))
      .max(Comparator.comparingDouble(Pair::getRight))
      .get();
}

6.2. ImmutableTriple fra Apache Commons Lang

ImmutableTriple er ret lig ImmutablePair . Den eneste forskel er, som navnet fortæller, en ImmutableTriple indeholder tre felter:venstre , midten, og højre.

Lad os nu tilføje en ny metode til vores koordinatberegning for at vise, hvordan man bruger ImmutableTriple type.

Vi vil gennemgå alle punkter i en Liste for at finde ud af min. , gennemsnit, og maks. afstande til det givne målpunkt.

Lad os se, hvordan vi kan returnere de tre værdier med en enkelt metode ved hjælp af ImmutableTriple klasse:

ImmutableTriple<Double, Double, Double> getMinAvgMaxTriple(
  List<Coordinates> coordinatesList, Coordinates target) {
    List<Double> distanceList = coordinatesList.stream()
      .map(coordinates -> coordinates.calculateDistance(target))
      .collect(Collectors.toList());
    Double minDistance = distanceList.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
    Double avgDistance = distanceList.stream().mapToDouble(Double::doubleValue).average().orElse(0.0D);
    Double maxDistance = distanceList.stream().mapToDouble(Double::doubleValue).max().getAsDouble();

    return ImmutableTriple.of(minDistance, avgDistance, maxDistance);
}

7. Konklusion

I denne artikel har vi lært, hvordan man bruger arrays, samlinger, containere og tupler til at returnere flere værdier fra en metode. Vi kan bruge arrays og samlinger i simple tilfælde, da de omslutter en enkelt datatype.

På den anden side er beholdere og tupler nyttige til at skabe komplekse typer, hvor beholdere giver bedre læsbarhed.

Vi lærte også, at nogle tredjepartsbiblioteker har implementeret par- og tredobbelte typer og så nogle eksempler fra Apache Commons Lang-biblioteket.

Som sædvanlig er kildekoden til denne artikel tilgængelig på GitHub.


Java tag