Comparez Java 8 en option avec Swift

Aperçu

Dans cet article, basé sur les éléments de l'aperçu des Documents officiels Apple en option, le type ʻOptional de Swift et Java 8 Types ʻCompare Optional. Bien que le contenu soit un peu rafraîchissant maintenant, je l'ai publié en tant que note personnelle. Fin de l'article comprend également un tableau de comparaison de chaque notation. Veuillez les regarder tous ensemble. Les extraits de code de cet article ont été un peu simplifiés, de sorte que certains d'entre eux ne fonctionneront pas même si vous les copiez et collez tels quels. Notez s'il vous plaît.

Opérateur Nil-Coalescing

Swift

Déballez ʻOptinal pour renvoyer le contenu, le cas échéant, ou la valeur par défaut spécifiée dans le cas contraire. Utilisez l'opérateur «??». Vous pouvez également connecter plusieurs types ʻOptional comme opérandes.

Swift


let wrappedValue: String? = nil
let defaultValue = "default"
let value = wrappedValue ?? defaultValue
print(value)
// "default"

Swift


let wrappedValue: String? = nil
let defaultValue = "default"

let otherWrappedValue: String? = nil
//Tant que l'opérande droit est facultatif??Peut être connecté avec
let value = wrappedValue ?? otherWrappedValue ?? defaultValue
print(value)
// "default"

Java 8

Dans Java 8, ce n'est pas un opérateur mais une méthode appelée ʻorElse, ʻorElseGet. ʻOrElse transmet la valeur par défaut elle-même, et ʻorElseGet transmet un objet de typeSupplier <? Etend T>qui fournit la valeur par défaut. Cependant, les deux méthodes retournent un type encapsulé, donc vous ne pouvez pas connecter les types ** facultatifs avec ʻou Sinon comme Swift **.

Java


Optional<String> wrappedValue = Optional.empty();
String defaultValue = "default";
String value = wrappedValue.orElse(defaultValue);
System.out.println(value);
// "default"

String otherValue = wrappedValue.orElseGet( () -> defaultValue );
System.out.println(otherValue);
// "default"

Java


Optional<String> otherWrappedValue = Optional.of("other");
//Je ne peux pas faire ça
// String unwrappedValue = wrappedValue.orElse(otherWrappedValue).orElse(defaultValue);

Évaluation des courts-circuits

Swift

L'opérateur de jointure Nil de Swift évalue le court-circuit. Par conséquent, l'opérande droit ne sera pas évalué à moins que l'opérande gauche ne soit «nil».

Swift


func hoge() -> String {
    print("called")
    return "hoge"
}

let value = nil ?? hoge()
print(value)
// "called"
// "hoge"

//Puisqu'il s'agit d'une évaluation de court-circuit, hoge()N'est pas appelé
let value = "non nil" ?? hoge()
print(value)
// "non nil"

Java 8

ʻOu Else Get de Java 8 est aussi une évaluation de court-circuit, mais ** ʻou Else ne le fait pas **. C'est naturel car la valeur par défaut elle-même est transmise.

Java


public String hoge() {
    System.out.println("called");
    return "hoge";
}

String value = Optional.<String>empty().orElseGet(this::hoge);
System.out.println(value);
// "called"
// "hoge"

//Puisqu'il s'agit d'une évaluation de court-circuit, hoge()N'est pas appelé
String value = Optional.of("non null").orElseGet(this::hoge);
System.out.println(value);
// "non null"

Java


//orElse n'évalue pas le court-circuit
String value = Optional.of("non null").orElse(hoge());
System.out.println(value);
// "called"
// "non null"

En ce qui concerne une utilisation correcte, si cela coûte de l'argent pour générer la valeur par défaut, il est préférable d'utiliser ʻorElseGet` pour l'évaluation des courts-circuits.

Java


public String fetchValue() {
    //Processus chronophage
    return result;
}

// △ -Assurez-vous de récupérerValeur()Est appelé, donc au moins cela affecte les performances
String value = wrappedValue.orElse(fetchValue());
// ◯ -Puisqu'il s'agit d'une évaluation de court-circuit, elle ne sera pas appelée s'il y a du contenu
String value = wrappedValue.orElseGet(this::fetchValue);

Java


// △ -S'il y a du contenu, ce sera la génération d'objets inutile
Person person = wrappedPerson.orElse(new Person());
// ◯ -Puisqu'il s'agit d'une évaluation de court-circuit, aucun objet ne sera créé s'il y a du contenu
Person person = wrappedPerson.orElseGet(Person::new);

Déballage inconditionnel

Swift

Décompresse la valeur avec ou sans contenu. Utilisez l'opérateur «!». S'il est "nil", cela provoquera une erreur d'exécution.

Swift


let number = Int("42")!
print(number)
// 42

Java 8

Java 8 utilise la méthode get. S'il est «null», une exception non vérifiée «NoSuchElementException» est levée.

Java


public Optional<Integer> intFromString(String string) {
    try {
        return Optional.of(Integer.parseInt(string));
    } catch (NumberFormatException ignored) {
        return Optional.empty();
    }
}

int number = intFromString("42").get();
System.out.println(number);
// 42

conversion

Swift

Convertissez la valeur. Utilisez une méthode appelée map. S'il y a du contenu, la valeur est convertie selon la fermeture de type (Wrapped) -> U donnée, et si elle est" nulle ", elle est transmise comme" nil ". Par conséquent, il renvoie le type ʻOptional`.

Swift


let intString: String? = "42"
let percentage: String? = intString.map { "\($0)%" }
print(String(describing: percentage))
// Optional("42%")

Si vous voulez retourner un type ʻOptional dans une fermeture, utilisez la méthode flatMapqui prend une fermeture de type(Wrapped) -> Optional ` comme argument.

Swift


let intString: String? = "42"
// Int(String)Est Int?rends le
let integer: Int? = intString.flatMap { Int($0) }
print(String(describing: integer))
// Optional(42)

Java 8

Java 8 utilise également les méthodes map et flatMap. L'utilisation est la même.

Java


Optional<String> intString = Optional.of("42");
Optional<String> percentage = intString.map( str -> str + "%" );
System.out.println(percentage);
// Optional[42%]

Java


Optional<String> intString = Optional.of("42");
Optional<Integer> integer = intString.flatMap(this::intFromString);
System.out.println(integer);
// Optional[42]

Reliure facultative

Swift

Je pense que c'est une méthode de déballage sûre. En combinant avec des mots-clés tels que «if» et «guard», il est possible de brancher le processus selon qu'il y a du contenu ou non.

Swift


let wrappedValue: String? = "value"
if let value: String = wrappedValue {
    print(value)
} else {
    print("no value")
}
// "value"

Swift


let wrappedValue: String? = "value"
guard let value: String = wrappedValue else {
    print("no value")
    return
}
print(value)
// "value"

Java 8

Dans Java 8, vous pouvez le dérouler en toute sécurité via une méthode appelée ʻifPresent`. Il prend un objet de type «Consumer <? Super T>» comme argument et décrit le traitement lorsqu'il contient un contenu.

Java


Optional<String> wrappedValue = Optional.of("value");
wrappedValue.ifPresent( str -> {
    System.out.println(str);
});
// "value"

Cependant, il n'y a pas de ** méthode qui puisse décrire le traitement lorsqu'il n'y a pas de contenu **. Par conséquent, si vous voulez décrire les deux processus, vous devez utiliser ʻis Presentpour vérifier l'existence du contenu. Cependant, il est redondant par rapport à Swift car vous devez décrire explicitement le déroulement forcéget` s'il y a du contenu **.

Java


Optional<String> wrappedValue = Optional.of("value");
if (wrappedValue.isPresent()) {
    //Redondant mais doit être explicitement déballé forcé
    String value = wrappedValue.get();
    System.out.println(value);
} else {
    System.out.println("no value");
}
// "value"

Java


Optional<String> wrappedValue = Optional.of("value");
//Décrire dans la clause de la carte
if (!wrappedValue.isPresent()) {
    System.out.println("no value");
    return;
}
//Redondant mais doit être explicitement déballé forcé
String value = wrappedValue.get();
System.out.println(value);
// "value"

Java


Optional<String> wrappedValue = Optional.of("value");
wrappedValue.ifPresent( str -> {
    System.out.println(str);
})// .orElse( () -> { //Je ne peux pas faire ça
//     System.out.println("no value");
// })
;

De plus, puisque la portée du processus passé à ʻifPresent` est dans l'expression lambda, la méthode appelante ne peut pas être retournée dans ce processus. Par conséquent, si vous souhaitez effectuer un retour anticipé, vous n'avez pas d'autre choix que d'utiliser «is Present».

Java


public boolean foo(Optional<String> wrappedValue) {
    //Revenir tôt s'il y a une valeur
    if (wrappedValue.isPresent) {
        String str = wrappedValue.get();
        //Faire quelque chose
        return true;
    }
    //Que faire s'il n'y a pas de valeur
    return result;
}

Java


public boolean foo(Optional<String> wrappedValue) {
    //Revenir tôt s'il y a une valeur
    wrappedValue.ifPresent( str -> {
        //Faire quelque chose
//         return true; //Cela n'est pas possible car la portée se trouve dans cette expression lambda
    });
    //Que faire s'il n'y a pas de valeur
    return result;
}

Chaînage facultatif

Swift

Accédez aux propriétés et aux méthodes uniquement lorsqu'il y a du contenu. Utilisez l'opérateur postfix «?».

Swift


let wrappedValue: String? = "value"
let uppercased: String? = wrappedValue?.uppercased()
print(String(describing: uppercased))
// Optional("VALUE")

Swift


class Hoge {
    func hoge() { print("hoge") }
}

let wrappedValue: Hoge? = Hoge()
wrappedValue?.hoge()
// "hoge"

Java 8

Dans Java 8, vous pouvez utiliser la méthode map introduite précédemment. Si la cible est une méthode, elle peut être écrite de manière concise à l'aide d'une référence de méthode. Cependant, si la cible renvoie un type ʻOptional, vous devez utiliser flatMap`.

Java


Optional<String> wrappedValue = Optional.of("value");
Optional<String> uppercased = wrappedValue.map(String::toUpperCase);
System.out.println(uppercased);
// Optional[VALUE]

Java


class User {
    final String id;
    Optional<String> mail = Optional.empty();
    User(String id) { this.id = id; }
}

Optional<User> wrappedUser = Optional.of(new User("user1"));
Optional<String> mail = wrappedUser.flatMap( user -> user.mail );
System.out.println(mail);
// Optional.empty

C'est exactement la même notation que lors de l'utilisation de Convert, y compris comment l'utiliser correctement. Java 8 ne fournit aucune notation ou méthode spéciale uniquement pour accéder au champ ou à la méthode de la valeur encapsulée. Pour accéder à une méthode qui ne renvoie pas de valeur, utilisez ʻifPresent` introduit précédemment.

Java


class Hoge {
    void hoge() { System.out.println("hoge"); }
}

Optional<Hoge> wrappedValue = Optional.of(new Hoge());
wrappedValue.ifPresent(Hoge::hoge);
// "hoge"

Résumé

Dans cet article, nous avons comparé les types Java 8 et ʻOptional basés sur la gestion des types ʻOptional dans Swift. Voici un tableau de comparaison de chaque notation. Surtout en ce qui concerne la reliure optionnelle et le chaînage optionnel, la différence entre les deux est très apparente. La liaison optionnelle Java 8 est un peu plus redondante que Swift car elle ne peut pas être déroulée en même temps que le branchement. De plus, Java 8 ne fournit pas de moyen dédié pour accéder aux valeurs encapsulées, telles que l'opérateur ? De Swift.

Swift Java
Opérateur de jointure nul ?? orElse* Évaluation sans court-circuit
orElseGet
Déballage forcé ! get
conversion map
flatMap
map
flatMap
Reliure facultative if let
guard let
ifPresent
OuisPresentAprès avoir ramifié àgetDéballage forcé avec
Chaînage facultatif ? OptionalSi vous souhaitez renvoyer le typeflatMap
Si vous retournez autre chosemap
S'il ne renvoie pas de valeurifPresent

Si vous avez des erreurs, veuillez nous en informer dans les commentaires.

Bonus-Java 9 en option

Ici, nous allons introduire les méthodes ʻOptional, ʻor et ʻifPresentOrElse`, ajoutées dans Java 9. Je ne peux pas parler de Java 8. C'est un bonus complet.

or

Exécute un objet de type Fournisseur <? Etend Facultatif <? Etend T >> donné lorsqu'il n'y a pas de contenu pour obtenir la valeur par défaut de type ʻOptional. C'est exactement le cas avec l'opérateur de jointure Nil de Swift apportant le type ʻOptional au bon opérande. De plus, en raison de l '** évaluation de court-circuit **, l'objet Supplier donné ne sera pas exécuté tant qu'il a un contenu.

Swift


let wrappedValue: String? = nil
let defaultValue = "default"

let otherWrappedValue: String? = nil
let value = wrappedValue ?? otherWrappedValue ?? defaultValue
print(value)
// "default"

Java


// available Java 9 or later
Optional<String> wrappedValue = Optional.empty();
String defaultValue = "default";

Optional<String> otherWrappedValue = Optional.empty();
//Le type facultatif peut être spécifié comme valeur par défaut dans Java 9 ou version ultérieure
String value = wrappedValue.or( () -> otherWrappedValue ).orElse(defaultValue);
System.out.println(value);
// "default"

ifPresentOrElse

Vous pouvez dériver le processus selon qu'il contient ou non un contenu. S'il y a du contenu, un objet de type Consumer <? Super T> est exécuté, sinon un objet de type Runnable est exécuté. Étant donné que vous pouvez également décrire le traitement lorsqu'il est «nul», il est beaucoup plus proche de la liaison optionnelle de Swift par rapport à Java 8.

Swift


let wrappedValue: String? = "value"
if let value = wrappedValue {
    print(value)
} else {
    print("no value")
}
// "value"

Java


// available Java 9 or later
Optional<String> wrappedValue = Optional.<String>empty();
wrappedValue.ifPresentOrElse( str -> {
    System.out.println(str);
}, () -> {
    System.out.println("no value");
});
// "no value"

Recommended Posts

Comparez Java 8 en option avec Swift
Réécrire Java try-catch avec facultatif
[Java] Résumez comment comparer avec la méthode equals
Compare Integer avec ==
24 heures de difficulté avec le développement Android, Java en option
[Java] Mémorandum facultatif
Java 9 Facultatif :: stream
Installez java avec Homebrew
Installez Java avec Ansible
Téléchargement confortable avec JAVA
Afficher la documentation Java de Java Facultatif
Changer java avec direnv
Recherche optionnelle Swift
Comparer des listes en Java
Premiers pas avec Swift
Téléchargement Java avec Ansible
Raclons avec Java! !!
À partir de Swift Swift UI
Construire Java avec Wercker
Conversion Endian avec JAVA
(Java) BDD facile avec Spectrum?
Utiliser des couches Lambda avec Java
Premiers pas avec Java Collection
Configuration Java avec Spring MVC
Authentification de base avec Java 11 HttpClient
Expérimentons l'expansion en ligne Java
Exécuter un lot avec docker-compose avec Java batch
[Template] Connexion MySQL avec Java
Installez Java 7 avec Homebrew (cask)
[Java] Communication JSON avec jackson
Java pour jouer avec Function
Essayez la connexion DB avec Java
Comment gérer les exceptions froidement avec Java 8 Stream ou en option
Comment utiliser java Facultatif
Activer Java EE avec NetBeans 9
[Java] JavaConfig avec classe interne statique
Essayez gRPC avec Java, Maven
Exploitons Excel avec Java! !!
Gestion des versions Java avec SDKMAN
Cryptage / décryptage RSA avec Java 8
Pagination de PDF avec Java + PDFBox.jar
Trier les chaînes comme une fonction caractéristique avec Java
Orienté objet avec Strike Gundam (java)
[Java] Acquisition de contenu avec HttpCliient
Gestion des versions Java avec jenv
Dépannage avec Java Flight Recorder
Rationalisez les tests Java avec Spock
Connectez-vous à DB avec Java
Connectez-vous à MySQL 8 avec Java
Utilisation de Mapper avec Java (Spring)
Mémo d'étude Java 2 avec Progate
[Swift] J'ai pensé à comparer
Premiers pas avec les bases de Java
Utiliser SpatiaLite avec Java / JDBC
Assurez-vous de comparer le résultat Java compareTo avec 0
Étudier Java avec Progate Note 1