-tandis que avec Java8-Facultatif
Je suis souvent à l'aide de le faire-tout-en-checkNextForNull-getNext boucle motif (ne sais pas si il y a un nom officiel) dans certains de mes projets. Mais dans Java8, l'utilisation de l'Option est considérée comme nettoyeur de code de vérification de références nulles en client-code. Mais lors de l'utilisation en Option dans cette boucle motif, le code est un peu verbeux et moche, mais parce que l'Option a une certaine pratique de méthodes, je m'attends à ce qu'il doit exister une façon plus propre que celle que j'ai trouvé ci-dessous.
Exemple:
Compte tenu de la classe suivante.
class Item {
int nr;
Item(nr) {
this.nr = nr;
//an expensive operation
}
Item next() {
return ...someCondition....
? new Item(nr + 1)
: null;
}
}
Dans lequel le premier élément a toujours nr==1 et chaque élément détermine l'élément suivant, et vous ne voulez pas créer inutilement de nouveaux éléments.
J'pouvez utiliser la boucle do-while-checkNextForNull-getNext modèle client-code:
Item item = new Item(1);
do {
//do something with the item ....
} while ((item = item.next()) != null);
Avec Java8-en Option, la classe devient:
class Item {
....
Optional<Item> next() {
return ...someCondition....
? Optional.of(new Item(nr + 1))
: Optional.empty();
}
}
Et puis, le faire-tout-en-checkNextForNull-getNext boucle motif devient un peu moche et verbose:
Item item = new Item(1);
do {
//do something with the item ....
} while ((item = item.next().orElse(null)) != null);
La orElse(null)) != null
partie se sent mal à l'aise.
J'ai regardé pour d'autres types de boucles, mais je n'ai pas trouvé mieux. Est-il une solution plus propre?
Mise à jour:
Il est possible d'utiliser une boucle for-each, tout en évitant en même temps null références (l'utilisation de null-références est considéré comme une mauvaise pratique). Cette solution a été proposée par Xavier Delamotte, et n'a pas besoin de Java8-Facultatif.
Mise en œuvre avec un générique itérateur:
public class Item implements Iterable<Item>, Iterator<Item> {
int nr;
Item(int nr) {
this.nr = nr;
//an expensive operation
}
public Item next() {
return new Item(nr + 1);
}
public boolean hasNext() {
return ....someCondition.....;
}
@Override
public Iterator<Item> iterator() {
return new CustomIterator(this);
}
}
et
class CustomIterator<T extends Iterator<T>> implements Iterator<T> {
T currentItem;
boolean nextCalled;
public CustomIterator(T firstItem) {
this.currentItem = firstItem;
}
@Override
public boolean hasNext() {
return currentItem.hasNext();
}
@Override
public T next() {
if (! nextCalled) {
nextCalled = true;
return currentItem;
} else {
currentItem = currentItem.next();
return currentItem;
}
}
}
Puis code client devient très simple/nettoyage:
for (Item item : new Item(1)) {
//do something with the item ....
}
Même si cela peut être considéré comme une violation de l'Itérateur contrat en raison de la new Item(1)
objet est inclus dans la boucle, alors que normalement, la boucle serait immédiatement appel à next() et donc de sauter le premier objet. En d'autres termes: pour le premier objet, next() est violé parce qu'il renvoie le premier objet lui-même.
Iterable
et vous donne un Iterator
à la place ? Vous avez juste à mettre en œuvre hasNext()
(ce qui est votre condition booléenne) et next
, au lieu de la mise en œuvre uniquement next()
.d'accord, cela sent (encore une autre), la surutilisation de l'Java8 featureset. c'est une bonne question, OP.
Iterator
est notoirement difficile à mettre en œuvre sur IO sources. Pour savoir si c'est hasNext
, il a fait de lire et de mettre en cache l'élément suivant. Curseur-comme les expressions idiomatiques, en s'appuyant uniquement sur la méthode unique, sont en fait préféré. Par exemple, Spliterator
utilise cette approche, avec une torsion.En effet. Cependant Goyave offres pour l'utilisation de AbstractIterator pour simplifier la mise en œuvre de ces itérateurs. code.google.com/p/guava-libraries/wiki/...
Le wrapper toujours pas aider le fait que
hasNext
est censé être un effet secondaire de la méthode avec des pas de temps de latence. Surtout noter les difficultés résultant de la nécessité de signal erreurs d'e/S pour le client.
OriginalL'auteur Devabc | 2015-02-26
Vous devez vous connecter pour publier un commentaire.
Vous pouvez faire quelque chose comme ceci :
ou (pour éviter la variable supplémentaire) :
orElse(null)) != null
. Merci!OriginalL'auteur Eran
Non, c'est l'inverse: en Option peut être utilisé là où il aide écrire nettoyeur de code. Il n'est pas, il suffit de coller à l'ancien idiome. Ne ressens pas de pression à l'utiliser si votre idiome semble bien—et il n'est, à mon avis. Comme un exemple, ce serait bien de l'utilisation de l'Option:
Car vous avez besoin de sortir de la boucle sur le premier non-présents en Option, ce n'est pas vraiment utile.
Cependant, je suppose que votre véritable intérêt est d'ordre plus général: exploiter les fonctionnalités de Java 8 pour votre code. L'abstraction vous devez choisir est du Flux:
Et, naturellement, vous pouvez maintenant aller sauvage avec traitement de flux:
Voici comment vous pouvez construire du flux:
Avec cela, vous êtes un petit pas loin de la capacité à s'intégrer harmonieusement paralléliser le calcul en cours. Depuis votre élément de flux est fondamentalement séquentiel, je vous suggère de regarder dans mes post de blog sur ce sujet.
OriginalL'auteur Marko Topolnik
Il suffit d'ajouter la prise en charge de boucle de votre API:
Alors il suffit d'itérer via lambda expression
ou de la méthode références
Si vous voulez soutenir les opérations plus sophistiquées que juste les boucles forEach, soutenir les flux de est la bonne façon de faire. C'est la même que la mise en œuvre encapsule comment itérer sur les
Item
s.for (Item i = this; i != null; i = i.next())
à la place. Puis cela devient une méthode de modèle juridique pour n'importe quel Élément de la sous-classe (en fait, un candidat parfait pour unedefault
la méthode de l'interface siItem
pourrait être prélevée en un).Topolnik: qui serait raisonnable, si les sous-classes sont jamais considérés. Je ne pouvais pas tirer ce à partir de la question d'origine.
OriginalL'auteur Holger
Puisque c'est lié à un certain type de conception que j'ai de venir avec au-dessous de la conception.
Créer l'interface qui prennent en charge pour fournir de l'option suivante.
Élément de mettre en œuvre NextProvidble interface.
J'utilise ici /...someCondition..../que nr < 10
Et de la nouvelle classe pour Coutume de Faire Tout comme ci-dessous.
Maintenant ce que vous avez à faire dans votre code client.
Il peut très clair.
S'il vous plaît ajouter vos pensées.
OriginalL'auteur Chamly Idunil
Déposer une autre alternative qui est disponible depuis Java 9.
Où
doSomething(Item item)
est la méthode qui fait quelque chose avec l'élément.OriginalL'auteur jbx