[Mémo] Comment utiliser Google MµG

Un mémo sur l'utilisation de la bibliothèque Google MµG, une bibliothèque utilitaire pour Java 8.

Dépendances

dependencies {
    compile 'com.google.mug:mug:1.12'
}

BiStream

Stream avec clé et valeur.

Créer un BiStream

Utilisez la méthode statique de BiStream.

biStream()

var input = Stream.of( "foo", "bar", "buz" );
var result = BiStream.biStream( input )
                     .mapValues( e -> e.toUpperCase() )
                     .toMap();
assertThat( result ).containsExactly( "foo", "FOO", "bar", "BAR", "buz", "BUZ" );

Enveloppez un Stream normal. Quand on se demande quoi utiliser, il semble que ce soit pour appeler une opération comme mapKeys () par la suite.

var input = Stream.of( "foo", "bar", "buz" );
var result = BiStream.biStream( input, Function.identity(), e -> e.toUpperCase() )
                     .toMap();
assertThat( result ).containsExactly( "foo", "FOO", "bar", "BAR", "buz", "BUZ" );

Une version qui prend une fonction de mappage comme argument.

from()

var input = Map.of( "foo", "123", "bar", "456", "buz", "789" );
var result = BiStream.from( input )
                     .map( ( i, v ) -> i + ":" + v )
                     .collect( toList() );
assertThat( result ).containsExactly( "foo:123", "bar:456", "buz:789" );

Créez un BiStream avec la clé de la carte et la valeur en tant que paire.

indexed()

var input = Stream.of( "foo", "bar", "buz" );
var result = BiStream.indexed( input )
                     .map( ( i, v ) -> i + ":" + v )
                     .collect( toList() );
assertThat( result ).containsExactly( "0:foo", "1:bar", "2:buz" );

Ajoutez un index à partir de 0. C'est bien car il est intégré aux API standard de la plupart des langages de programmation. Le type de retour est «BiStream <Integer, V>». Les types primitifs ne sont pas pris en charge comme prévu.

neighbors()

var input = Stream.of( "foo", "bar", "buz" );
var result = BiStream.neighbors( input )
                     .map( ( i, v ) -> i + ":" + v )
                     .collect( toList() );
assertThat( result ).containsExactly( "foo:bar", "bar:buz" );

Associez deux valeurs adjacentes.

of()

var result = BiStream.of( "foo", "123", "bar", "456" )
                     .map( ( i, v ) -> i + ":" + v )
                     .collect( toList() );
assertThat( result ).containsExactly( "foo:123", "bar:456" );

Similaire au standard JDK ʻof () `.

zip()

var input1 = Stream.of( "foo", "bar", "buz" );
var input2 = Stream.of( "hoge", "piyo", "fuga" );
var result = BiStream.zip( input1, input2 )
                     .map( ( t, u ) -> t + ":" + u )
                     .collect( toList() );
assertThat( result ).containsExactly( "foo:hoge", "bar:piyo", "buz:fuga" );

Combinez les deux Streams. J'ai toujours fait ça moi-même. Pour être honnête, le niveau que je veux que vous ajoutiez à la bibliothèque standard. Cependant, notez que si la taille de «Stream» est différente, le reste sera ignoré selon le plus petit.

var input1 = Stream.of( "foo", "bar", "buz" );
var input2 = Stream.of( "hoge", "piyo" );
var result = BiStream.zip( input1, input2 )
                     .map( ( t, u ) -> t + ":" + u )
                     .collect( toList() );

assertThat( result ).containsExactly( "foo:hoge", "bar:piyo" );

Utilisez BiStream

append()

var result = BiStream.of( "foo", "123" ).append( "bar", "456" )
                     .map( ( t, u ) -> t + ":" + u )
                     .collect( toList() );
assertThat( result ).containsExactly( "foo:123", "bar:456" );

Ajoutez une valeur après.

inverse()

var result = BiStream.of( "foo", "123", "bar", "456" )
                     .inverse()
                     .map( ( t, u ) -> t + ":" + u )
                     .collect( toList() );
assertThat( result ).containsExactly( "123:foo", "456:bar" );

Échangez des valeurs contre des clés. Je veux que vous l'ajoutiez au standard Stream ...

MoreStream

Fournit des extensions introuvables dans JDK ou Guava.

generate()

var result = MoreStreams.generate( 1, n -> n >= 9 ? Stream.empty() : Stream.of( n + 1 ) )
                        .collect( toList() );
assertThat( result ).containsExactly( 1, 2, 3, 4, 5, 6, 7, 8, 9 );

Une méthode pour générer des flux * finis *. Arrêtez la génération lorsqu'un flux vide est renvoyé. Y a-t-il une utilité pour cela?

flatten()

var input = Stream.of(
        Stream.of( "foo", "bar", "buz" ),
        Stream.of( "hoge", "piyo", "fuga" )
);
var result = MoreStreams.flatten( input )
                        .collect( toList() );
assertThat( result ).containsExactly( "foo", "bar", "buz", "hoge", "piyo", "fuga" );

Le même processus devrait être possible avec flatMap, mais il existe cette méthode car elle ne peut pas gérer des flux infinis à cause d'un bogue Java. Il semble que cela ait été corrigé dans JDK 10.

dice()

var input = Stream.of( "foo", "bar", "buz", "hoge", "piyo" );
var result = MoreStreams.dice( input, 2 )
                        .collect( toList() );
assertThat( result.size() ).isEqualTo( 3 );
var list1 = result.get( 0 );
assertThat( list1 ).containsExactly( "foo", "bar" );
var list2 = result.get( 1 );
assertThat( list2 ).containsExactly( "buz", "hoge" );
var list3 = result.get( 2 );
assertThat( list3 ).containsExactly( "piyo" );

Listez les Streams par taille spécifiée et mettez-les ensemble dans une nouvelleStream <List>. Pour les flux séquentiels, il est garanti qu'une liste de la taille spécifiée sera renvoyée sauf à la fin du flux. Non garanti pour les flux parallèles.

En passant, j'ai appris pour la première fois qu'une telle opération s'appelle «dés». En quoi est-ce différent de "window"?

iterateOnce()

var input = Stream.of( "foo", "bar", "buz" );
for ( var e : MoreStreams.iterateOnce( input ) ) {
    assertThat( e ).isAnyOf( "foo", "bar", "buz" );
}

Une méthode pour itérer un flux avec une instruction for. Peut-être que je ne l'utiliserai pas pour le reste de ma vie.

iterateThrough()

expect(() -> {
    MoreStreams.iterateThrough( Stream.of( "foo" ), e -> {
        throw new Exception( "Checked Exception!" );
    });
}).throwsException( e -> {
    assertThat( e ).hasMessageThat().isEqualTo( "Checked Exception!" );
});

C'est fondamentalement la même chose que forEach (), à la différence que vous pouvez lancer une exception vérifiée.

Retryer

Un processus pour réessayer un processus qui peut échouer. Je pense que c'est pratique, mais la plupart des processus qui nécessitent de nouvelles tentatives sont fournis avec une fonction de nouvelle tentative, donc c'est étonnamment inutile.

  1. Créez une instance de Retryer.
  2. Spécifiez les conditions de nouvelle tentative avec ʻupon () , ʻifReturns (), etc.
  3. Spécifiez l'intervalle d'exécution avec Delay. Dans la plupart des cas, vous pouvez utiliser ʻexponentialBackoff () `pour doubler l'intervalle de relance.
  4. Spécifiez le processus à réessayer avec retryBlockingly (), retry (), retryAsync ().

Synchroniser

var result = new Retryer()
        .upon( RuntimeException.class, Retryer.Delay.ofMillis( 100 ).exponentialBackoff( 2, 2 ) )
        .retryBlockingly( this::mayFail );
assertThat( result ).isEqualTo( "success" );

asynchrone

CompletionStage<String> future = new Retryer()
        .upon( RuntimeException.class, Retryer.Delay.ofMillis( 100 ).exponentialBackoff( 2, 2 ) )
        .retry( this::mayFail, Executors.newSingleThreadScheduledExecutor() );
future.thenAccept( result -> {
    assertThat( result ).isEqualTo( "success" );
});

Pour être honnête, l'API asynchrone est subtile.

Maybe

Une classe pour le traitement d'encapsulation qui peut déclencher une exception. Quelque chose comme une version de java.util.Optional avec la capacité de gérer les exceptions. Est-ce que Try est relativement proche dans Scala?

Le but principal semble être de gérer facilement les exceptions vérifiées dans les flux.

maybe()

La méthode de base pour créer une instance Maybe. Accepte diverses interfaces fonctionnelles.

var result = IntStream.range( 1, 10 ).boxed()
                      .map( Maybe.maybe( e -> {
                          if ( e <= 5 ) {
                              return e;
                          } else {
                              throw new Exception();
                          }
                      } ) )
                      .map( m -> m.orElse( e -> Integer.valueOf( 0 ) ) )
                      .collect( toList() );
assertThat( result ).containsExactly( 1, 2, 3, 4, 5, 0, 0, 0, 0 );

La valeur qui a provoqué une exception dans ʻorElse () est convertie en 0`.

expect(() -> {
    Maybe.maybe( () -> { throw new RuntimeException( "Unchecked!" );} );
}).throwsException( e -> {
    assertThat( e ).hasMessageThat().isEqualTo( "Unchecked!" );
});

Les exceptions non vérifiées sont renvoyées telles quelles. Mise en garde. Ce n'est pas qu'il peut être utilisé pour autre chose que des flux, mais en raison de cette limitation, je pense qu'il est préférable d'utiliser une bibliothèque dédiée.

byValue()

var result = IntStream.range( 1, 10 ).boxed()
                      .map( Maybe.maybe( e -> {
                          if ( e <= 5 ) {
                              return e;
                          } else {
                              throw new Exception();
                          }
                      } ) )
                      .filter( Maybe.byValue( n -> n % 2 == 0 ) )
                      .map( m -> m.orElse( e -> Integer.valueOf( 0 ) ) )
                      .collect( toList() );
assertThat( result ).containsExactly( 2, 4, 0, 0, 0, 0 );

Puisque filter () recevra Maybe, il existe une méthode pour déballer. Comme vous pouvez le voir, si une exception se produit, elle passe au traitement suivant.

1.PNG 2.PNG

catching()

var result = IntStream.range( 1, 10 ).boxed()
                      .map( Maybe.maybe( e -> {
                          if ( e <= 5 ) {
                              return e;
                          } else {
                              throw new Exception();
                          }
                      } ) )
                      .flatMap( m -> m.catching( e -> {} ) )
                      .collect( toList() );
assertThat( result ).containsExactly( 1, 2, 3, 4, 5 );

À utiliser lorsque vous souhaitez simplement ignorer la valeur.

Funnel

C'est tout un créneau à utiliser, mais cela semble pratique si vous devenez accro.

Cas d'utilisation

Funnel

var funnel = new Funnel<String>();
var batch = funnel.<String>through( data -> {
    assertThat( data ).containsExactly( "batch1", "batch2" );
    return data.stream().map( String::toUpperCase ).collect( toList() );
} );

var input = List.of( "local1", "batch1", "local2", "batch2" );
for ( var i : input ) {
    if ( i.startsWith( "local" ) ) {
        funnel.add( i );
    } else {
        batch.accept( i );
    }
}
var result = funnel.run();

assertThat( result ).containsExactly( "local1", "BATCH1", "local2", "BATCH2" );
  1. Tout d'abord, instanciez Funnel
  2. Utilisez la méthode through () pour spécifier le processus de conversion par lots.
  3. Appelez Funnel.add () pour que les valeurs soient traitées individuellement.
  4. Passez les valeurs à traiter ensemble à Funnel.Batch.accept ().
  5. Exécutez avec Funnel.run ().

Notez que ʻaccept () `a une surcharge qui prend une fonction qui convertit le résultat en argument.

var funnel = new Funnel<String>();
var batch = funnel.<String>through( data -> List.of() );
batch.accept( "batch1" );
expect(() -> {
    funnel.run();
}).throwsException( e -> {
    assertThat( e ).isInstanceOf( IllegalStateException.class );
});

Évidemment, si la taille de la liste de retour de lots est différente de l'entrée, vous obtiendrez une erreur.

var funnel = new Funnel<String>();
var batch = funnel.<String>through( data -> List.of() );
batch.accept( "batch1" );

expect(() -> {
    funnel.run();
}).throwsException( e -> {
    assertThat( e ).isInstanceOf( IllegalStateException.class );
});

La commande dépend de l'ordre de traitement par lots. Il est nécessaire de s'assurer que le processus revient dans le même ordre que l'entrée.

var funnel = new Funnel<String>();
var batch = funnel.<String>through( data -> {
    var newList = new ArrayList<String>( data );
    Collections.reverse( newList );
    return newList;
} );
batch.accept( "batch1" );
batch.accept( "batch2" );
var result = funnel.run();

assertThat( result ).containsExactly( "batch2", "batch1" );

Parallelizer

Comme son nom l'indique, parallélisez le traitement.

var input = Stream.of( "foo", "bar", "buz" );
var result = Collections.synchronizedList( new ArrayList<String>() );
new Parallelizer( executor, 3 )
        .parallelize( input, result::add );
assertThat( result ).containsExactly( "foo", "bar", "buz" );
  1. Instanciez Parallelizer. Les arguments sont ʻExecutorService pour exécuter le processus et le nombre de tâches qui peuvent être exécutées en même temps. Est-ce fondamentalement le même que le nombre de threads dans ʻExecutor Service?
  2. Appelez parallelize () ou parallelizeUninterruptably (). Le premier argument est Stream ou ʻIterator`, qui sont les données d'entrée, et le deuxième argument est le traitement à effectuer.

Le processus est bloqué jusqu'à ce qu'il se termine. Si une exception se produit au milieu, le traitement suivant est interrompu.

Selon README

Parallel streams are for CPU-bound tasks. JDK has built-in magic to optimally use the available cores. Parallelizer is for IO-bound tasks.

Il semble qu'il devrait être utilisé pour l'entrée / la sortie de fichiers, l'appel d'API externe, etc.

Résumé

Recommended Posts

[Mémo] Comment utiliser Google MµG
Comment utiliser Google Colaboratory
Comment utiliser cron (mémo personnel)
[Mémo] Comment utiliser BeautifulSoup4 (1) Afficher html
Comment utiliser Google Test en langage C
Comment utiliser l'Assistant Google sur Windows 10
Comment utiliser xml.etree.ElementTree
Comment utiliser Python-shell
Remarques sur l'utilisation de tf.data
Comment utiliser virtualenv
Comment utiliser Seaboan
Comment utiliser la correspondance d'image
Comment utiliser le shogun
Comment utiliser Pandas 2
Comment utiliser numpy.vectorize
Comment utiliser pytest_report_header
Comment utiliser partiel
Comment utiliser Bio.Phylo
Comment utiliser SymPy
Comment utiliser x-means
Comment utiliser WikiExtractor.py
Comment utiliser IPython
Comment utiliser Matplotlib
Comment utiliser iptables
Comment utiliser numpy
Comment utiliser TokyoTechFes2015
Comment utiliser venv
Comment utiliser le dictionnaire {}
Comment utiliser Pyenv
Comment utiliser la liste []
Comment utiliser python-kabusapi
Comment utiliser OptParse
Comment utiliser le retour
Comment utiliser pyenv-virtualenv
Comment utiliser imutils
Comment utiliser Qt Designer
Comment utiliser la recherche triée
[gensim] Comment utiliser Doc2Vec
python3: Comment utiliser la bouteille (2)
Comment utiliser le générateur
[Python] Comment utiliser la liste 1
Comment utiliser Python Argparse
Comment utiliser IPython Notebook
Comment utiliser Pandas Rolling
[Note] Comment utiliser virtualenv
Comment utiliser les dictionnaires redis-py
Python: comment utiliser pydub
[Python] Comment utiliser checkio
[Aller] Comment utiliser "... (3 périodes)"
Comment faire fonctionner GeoIp2 de Django
[Python] Comment utiliser input ()
Comment utiliser le décorateur
[Introduction] Comment utiliser open3d
Comment utiliser Python lambda
Comment utiliser Jupyter Notebook
[Python] Comment utiliser virtualenv
python3: Comment utiliser la bouteille (3)
python3: Comment utiliser la bouteille