150 votes

Java 8 et Scala

Cela Java 8 vs Scala : une comparaison des fonctionnalités article sur InfoQ, résume très bien les similitudes entre le prochain Java 8 et Scala.

Étant donné les améliorations à Java 8, quelles sont les fonctions en Scala qui serait toujours me motiver à adopter la Scala comme langue ?

Edit : J’utilise Java 7

248voto

om-nom-nom Points 33691

Certaines des fonctionnalités que je ne vois pas dans cet article mais ceux qui sont présentées dans Scala.

Des classes de cas

Le compilateur va générer toString, equals, hashCode et quelques autres choses pour vous. Considérons cet extrait de Java

public class Foo {

  final String bar;
  final String baz;

  Foo(String bar, String baz) {
    this.bar = bar;
    this.baz = baz;
  }

  // equals, toString and hashcode definitions

}

contre la Scala, à la classe de cas:

case class Foo(bar: String, baz: String)

Le Pattern matching

Vous pouvez considérer cela comme un interrupteur sur les stéroïdes:

case class Human(name: String, surname: String)
val tom: Human = Human("Tom", "Hanks")
def saySomething(t: Human): String = t match {
  case Human(_, "Hanks") => "Run Forrest, run!"
  case Human(_, "Hardy") => "No, Bane, no!"
}
println(saySomething(tom))

Cela peut conduire à de très belles API: ici est de savoir comment on peut utiliser des expressions régulières dans scala:

val LogEntry = """Completed in (\d+)ms \(View: (\d+), DB: (\d+)\) \| (\d+) OK \[http://app.domain.com(.*)\?.*""".r
val line = "Completed in 100ms (View: 25, DB: 75) | 200 OK [http://app.domain.com?params=here]"
val LogEntry(totalTime, viewTime, dbTime, responseCode, uri) = line

Voilà: maintenant, vous avez tempstotal, temps de vu, dbTime et d'autres variables prêt à être utilisé.

En fait, il a été utilisé un autre Scala fonctionnalité: déstructuration de cession qui est un autre type de pattern matching.

Combien de fois vous avez vu en java:

for(Map.Entry<Key,Value> entry: map.getEntrySet()) {
  Key key = entry.getKey();
  Value value = entry.getValue();
  // do something with them
}

En scala, extrait, comme cela pourrait ressembler à:

for((key,value) <- map) {
  // do something
}

Il y a beaucoup plus de cas d'utilisation de pattern matching.

L'inférence de Type

... a été montré un peu dans le code ci-dessus.

Au lieu d'écrire

val countriesToCapitals: Map[String, String] = Map("England" -> "London")
def foo(): SomeLongReturnType = {...}

Vous pouvez simplement écrire

val countriesToCapitals = Map("England" -> "London")
def foo() = {...}

Il enlève beaucoup plus de l'encombrement de code que vous pourriez le penser. Dans les endroits où vous avez besoin de type de nom, vous pouvez toujours écrire.

Plus nette de primitives et de la spécialisation. Les classes de valeur.

Contrairement à Java Entier, Scala Int (et de quelques autres types, par exemple Octet de Long, e.t.c.) se traduit dans les types primitifs au moment de la compilation, il n'y a pas de frais généraux au niveau de la JVM. Le programmeur travaille encore avec eux comme avec des types d'objet. En outre, dans Scala 2.10 vous pouvez utiliser les valeurs de classes.

Ces deux caractéristiques combinées de vous permettre de customiser chaque classe avec presque pas de coût d'exécution.

@tailrec annotation

Scala n'effectue pas seulement TCE (donc vous ne finirez pas avec un débordement de pile) où il peut, mais vous permet également de placer @tailrec annotation pour être sûr que la méthode est la queue récursive.

Si quelqu'un un jour modifier le code destiné à être la queue récursive dans la façon dont il n'est pas tailrecursive plus, vous obtiendrez l'erreur de compilation.

Traits

C'est comme les interfaces, mais vous permet d'écrire à la mise en œuvre des méthodes que vous avez définies.

Paresseux mot-clé

Vous pouvez définir des variables avec lazy mot-clé. Ils vont être initialisé à la demande au premier accès.

lazy val result = { 
  // ... here goes really heavy processing I want to avoid right now and make on call
}

De plus, si quelque chose se passe mal lors du premier appel , elle va essayer de ré-évaluer lui-même.

Paramétrable modificateurs d'accès

Vous pouvez régler l' protected et private des modificateurs d'accès à portée exacte. Par exemple

package foo.bar.baz

object Example {
  private[baz] def notSoPrivate = { ... } 
} 

Le modificateur peut être paramétré avec une classe englobante ou package.

Riche importations

En scala, vous pouvez importer des choses, non seulement dans le haut du fichier, mais littéralement partout. Cela peut conduire à des trucs.

Par exemple, il m'arrive souvent d'écrire ce genre de code, quand je suis le développement de Swing apps:

JFrame windowFrame = new JFrame()
windowFrame.setSize(300, 200);
windowFrame.getContentPane().setLayout(null);
windowFrame.add(getJLabel(), null);
windowFrame.add(getJTextField(), null);
windowFrame.add(getJButton(), null);
windowFrame.setTitle("HelloWorld");

Mais avec un petit truc:

val windowFrame = new JFrame()

{
  import windowFrame._

  setSize(300, 200);
  getContentPane().setLayout(null);
  add(getJLabel(), null);
  add(getJTextField(), null);
  add(getJButton(), null);
  setTitle("HelloWorld");
}

Vous pouvez également créer un alias pour des articles importés, comme

import foo.bar.baz.{ SomeVeryLongName => T}

// 

new T();

64voto

Péter Török Points 72981

Les Lambdas sont bien en effet, mais Scala a beaucoup plus de fonctionnalités non disponibles dans Java, comme

  • syntaxe plus concise, grâce en grande partie à compilateur de l'inférence de type,
  • le filtrage et des classes de cas,
  • pour-des compréhensions,
  • partielle des fonctions,
  • puissant système de type,
  • implicites,
  • qui, ensemble, permettent à des classes de type
  • les traits,
  • macros,
  • plus souple de la syntaxe,
  • paresseux de l'évaluation et des ruisseaux (activer l'utilisation de l'infini de séquences),
  • nourrissage...

juste pour faire un peu de qui vient à mon esprit.

31voto

Saint Hill Points 2285

Quel que soit les caractéristiques de la Scala, je trouve qu'il est très difficile à lire. Et oui, les petites bribes semble OK pour le lire, mais de grands programmes sembler intimidant. La lisibilité des projets complexes est mon #1 au mieux pour n'importe quelle langue. Pour la même raison, une énorme base de VB.net existe toujours et est préféré par beaucoup de développeurs par rapport à la plus capable C#.net -- code VB est facile à lire et à digérer.

Java est plus verbeux, sans aucun doute. Cependant, il est superbement documenté pour toutes sortes d'applications. En revanche, la Scala a très peu de soutien à l'apprentissage. Java 8 ajoute Lambdas, de nouvelles bibliothèques, et avec la plupart de ce que Java a déjà fait un très bon travail.

Lors de la comparaison de Java 8 et Scala, être conscient de ces problèmes

Les fonctionnalités qui sont vraiment caractéristiques

Maintenant, c'est un Scala fonctionnalité et j'espère Java 9 va faire quelque chose comme ceci:

case class Foo(bar: String, baz: String)

Pour générer une classe Java avec égal à égal, hashcode et toString, getters et setters,comme ça, eh bien, il serait un pain PITA. Cependant, je ne trouve pas moi-même de générer beaucoup de ces types de " cas " des classes.

Tout Foo que je fais, en général on a de la logique et de comportements sous les couvertures et de le faire est presque la même dans les deux Scala et Java.

Si je n'ai besoin de Java est quelque chose d'organiser un 'bar' et un 'baz', puis-je utiliser une Carte. C'est vrai, le tout-flexible, de fantaisie sans Carte!

Map map = new HashMap(){{
  put("bar","this is a bar entry");
  put("baz","this is a baz entry");
}}

Tout ce que je veux dire, c'est ... il y a des alternatives à des classes de cas et elles ne sont pas si difficile que de faire un plein de classe Java.

Pour ne pas dire que des classes de cas ne serait-il pas agréable (Java 9, écoutez-vous!) parce qu'ils sont vraiment une caractéristique de la valeur pour les quelques cas (no pun intended) où des cas, il permettrait de résoudre certains cas.

Les fonctionnalités qui sont vraiment non-caractéristiques

Scala

def saySomething(t: Human): String = t match {
  case Human(_, "Hanks") => "Run Forrest, run!"
  case Human(_, "Hardy") => "No, Bane, no!"
}
println(saySomething(tom))

Java

public String saySomething(Human human){
  switch(human.getSurname()){
       case: "Hanks" return "Run Forrest, run!";
       case: "Hardy" return "No, Bane, no!";
       default: return "";
  }
}

System.out.println(saySomething(tom))

C'est à peine une différence, si vous me demandez, et je trouve que le code Java est plus facile à comprendre.

Maintenant, j'ai été -1 avais pour ne pas montrer comment Scala Pattern Matching est tellement génial. Jusqu'à présent, quelqu'un a commenté avec cet exemple, Quel est l'avantage de l'utilisation de la scala de filtrage au lieu de java commutateur cas? Et franchement, ça semble compliqué, mais je ne vois pas l'intérêt de faire les choses de cette façon.

Java raccourcis souvent oubliée

Scala fans utilise des exemples de ce genre pour montrer ce que Scala peut faire. En regardant Riche importations dans la réponse sélectionnée ci-dessus, nous avons Java:

JFrame windowFrame = new JFrame()
windowFrame.setSize(300, 200);
windowFrame.getContentPane().setLayout(null);
windowFrame.add(getJLabel(), null);
windowFrame.add(getJTextField(), null);
windowFrame.add(getJButton(), null);
windowFrame.setTitle("HelloWorld");

Scala avec de riches importations

val windowFrame = new JFrame()

{
  import windowFrame._

  setSize(300, 200);
  getContentPane().setLayout(null);
  add(getJLabel(), null);
  add(getJTextField(), null);
  add(getJButton(), null);
  setTitle("HelloWorld");
}

Mais avec Java il est également possible de le faire de cette façon:

JFrame windowFrame = new JFrame(){{
   setSize(300, 200);
   getContentPane().setLayout(null);
   add(getJLabel(), null);
   add(getJTextField(), null);
   add(getJButton(), null);
   setTitle("HelloWorld");
   }};

De nouvelles fonctions Lambda

Évaluation Différée

En Scala, il y a le "paresseux" mot:

lazy val result = { 
  // ... here goes really heavy processing I want to avoid right now and make on call
} 

Java 8 a un Supplier<T> qui peut également memoize et a l'avantage de permettre une date d'expiration:

Supplier<Complex> result = Supplier.memoize( ()-> {
  // here goes really heavy processing
  })

Maintenant, je vais vous avouer que la Scala de code est concis. Cependant, il ne confère pas le type d'informations pour le programmeur d'un coup d'oeil. Je connais le Java 8 Fournisseur est de type 'T' ou dans le ci-dessus, de type 'Complexe'. Java 8 permet également l'utilisation d'une date d'expiration de la méthode:

Supplier<Complex> result = Supplier.memoizeWithExpiration(Supplier<T> delegate, long duration,TimeUnit unit)

Pour les Paresseux, j'aime bien le Java 8 mieux parce que: (a) Il confère type d'informations pour le programmeur; (b) c'est un 'Supplier qui décrit plus précisément la fonction que quelque chose peut-être qui n'existe pas déjà; (c) elle a une date d'expiration qui est très utile pour le web, les applications et le besoin de certains objets à être rafraîchi après une période de temps. Java 8 Fournisseur est thread-safe.

L'itération d'une Carte

Dans Java 8, à l'aide de Lambda rend également plus facile de travailler avec des collections et d'autres types. Il n'est plus besoin de le faire:

for(Map.Entry<Key,Value> entry: map.getEntrySet()) {
  Key key = entry.getKey();
  Value value = entry.getValue();
  // do something with them
}

Parce que maintenant vous pouvez le faire:

    m.forEach((k, v) -> System.out.println("key: " + k + " value: " + v));

Une boucle dans une plage de valeurs

Java 8 ajoute une nouvelle boucle mécanisme qui peut éventuellement être 1 ou 0 en fonction:

IntStream.rangeClosed(1,10).forEach( System.out::println );

Comparaison Des Pièges

À l'aide d'anciennes fonctionnalités

Il y a beaucoup de mauvais exemples de Java vs Scala, où l'auteur a utilisé le pire Java technique et l'a comparé avec le meilleur Scala technique.

Voici une comparaison des vieux Java pour le nouveau Java 8 vs Scala. L'auteur pose la question pour une fonction qui fait cela:

  • Entrée: Liste
  • Sortie: Carte>
  • La clé de la carte est 'A' à 'Z'
  • Chaque liste dans la carte sont triés.

Old Java

List<String> keywords = Arrays.asList("Apple", "Ananas", "Mango", "Banana", "Beer"); 
Map<Character, List<String>> result = new HashMap<Character, List<String>>(); 
for(String k : keywords) {   
    char firstChar = k.charAt(0);     
    if(!result.containsKey(firstChar)) {     
        result.put(firstChar, new  ArrayList<String>());   
    }     
    result.get(firstChar).add(k); 
} 
    for(List<String> list : result.values()) {   
       Collections.sort(list); 
    }
System.out.println(result);   

Java 8

List<String> keywords = Arrays.asList("Apple", "Ananas", "Mango", "Banana", "Beer");
Map<Character, List<String>> result = keywords.stream().sorted()
        .collect(Collectors.groupingBy(it -> it.charAt(0)));
System.out.println(result);

Scala

val keywords = List("Apple", "Ananas", "Mango", "Banana", "Beer")
val result = keywords.sorted.groupBy(_.head)
println(result)

Ainsi, vous pouvez le voir avec Java 8, si vous savez la nouvelle façon, vous pouvez réduire le code considérablement et il est également très facile à lire. Encore une fois, il n'y a pas beaucoup de différence, le cas échéant, entre le Java 8 et Scala dans cet exemple. Sans doute, la Java 8 Flux et les fonctions de Mappage maintenant peut-être mieux de la Scala.

Oublier d'utiliser utile bibliothèques

Il y a beaucoup de puissants bibliothèques Java qui n'beaucoup de ce qui est soigneusement présenté dans Scala et souvent beaucoup plus.

Bien sûr, vous pourriez créer votre propre code pour traiter les chaînes de caractères dans les Scala, et il aurait l'air plus propre, mais pourquoi ne pas juste prendre [http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html][1] et d'apprendre ce qu'il peut faire pour vous?

Conclusion

Quand vous voyez un Scala vs Java exemple, demandez-vous: est-ce que le meilleur, le plus souple, le plus concis moyen de le faire en Java? L'auteur n'a examiner populaire de Java bibliothèques open source? L'auteur montre le même code de gestion d'erreur dans chaque langue pour la mise en œuvre? L'auteur n'a omettre de l'information en tapant à faire Scala paraître plus propre?

Scala est en avance de Java, à de nombreux égards. Scala est plus rapide de prototype dans IFAIAC. Cependant, certains développeurs, la Scala, la langue est encore difficile de code et de le conserver.

Comme une alternative à Java, Groovy 2.0 vaut également le détour. Il peut maintenant être à la fois typées dynamiquement et statiquement typé (comme Java et Scala) et j'aime la syntaxe bien mieux que la Scala. Et il est même plus rapide que la Scala pour le prototypage. Groovy aussi travaille côte à côte avec Java et offre des capacités Web avec leur live systèmes de modèle. Groovy est de Java sur les stéroïdes. Groovy est juste incroyablement groovy.

J'encourage tout le monde à apprendre Scala et les maîtriser. Le plus intelligent que les développeurs seront également en Java pour et obtenir les meilleurs emplois parce qu'ils peuvent faire à la fois.

Pour le moment, je ne vois pas de raison convaincante pour passer de Java à la Scala basé sur les caractéristiques de la Scala offre. Ils sont sympas, mais pas de deal breakers pour moi. Vous vous décidez pour vous-même.

19voto

user2684301 Points 734
  • Propres propriétés. Bien mieux que Java ou C#. Pas plus trivial des accesseurs/mutateurs comme en Java. Pas plus de champs vs propriétés comme en C#.
  • L'inférence de Type pour les variables et les fonctions. Manière de mieux que de se limiter inférence de type en C#.
  • val déclare haut niveau de l'immutabilité. Bien mieux que surchargé final en Java, ou const/readonly en C# avec l'étrange règles associées.
  • "si" renvoie une valeur. pas besoin d'un opérateur ternaire au cas particulier d'un if/else qui retourne une valeur.
  • dernière instruction dans un bloc de code renvoie une valeur. fait pour beaucoup de concis, élégant code.
  • pour le rendement des expressions. la syntaxe natif de sucre pour n'importe quel type de carte+flatMap, y compris l'Option, une Liste, un Avenir, et les types personnalisés.
  • des "tableaux" utiliser la même syntaxe générique et les mêmes règles de conversion. Pas de cas particulier de la syntaxe et des règles comme en C++/Java/C# qui boulonné paramètres de type générique sur un langage existant. C++/Java/C# a aussi fait des tableaux covariante qui était une erreur, avec le recul. Scala ne pas faire cette erreur.
  • compagnon les objets sont de plus agréable que de "statique"
  • le pattern matching. c'est une grosse affaire.
  • construit-dans les tuples à la différence de Java/C#
  • spécial concis nourrissage de la syntaxe.
  • intégré partielle des fonctions.
  • this.type. Une fonction de classe peut faire return this à la sous-classe type. C#/Java ne peut pas le faire. JavaFX est de retirer toutes les classes de constructeur à cause de ce problème (déconseillé dans JavaFX 8, retiré dans le futur). L'OMI, l'équipe Java devraient avoir simplement ajouté la fonctionnalité du langage.
  • Les génériques peuvent gérer de primitives et d'éviter la plupart de boxe de pénalité. Array[Int] en fin de compte compile dans la JVM int[] instructions à zéro exécution perte d'efficacité. Java 8 met en œuvre des cours spécialisés comme l' IntStream pour éviter de boxe de sanctions, Stream<Integer> ce qui est mieux que rien, mais c'est un désordre de la solution. C# poignées de ce phénomène et permet d' List<int> sans la boxe.
  • Déclaration de type côté de la variance avec les génériques. C# 4.0 a cela aussi.

15voto

KajMagnus Points 2580

Scala fonctionnalité: Beaucoup moins de bugs!

Voici trois Scala fonctionnalités/les choses qui empêchent les trois sources les plus courantes de bugs:

  • L' Option, Certains et Aucun des classes qui (quelque peu simplifiée), éviter de pointeur null erreurs de se produire, en Scala.

  • Les paramètres nommés, qui (si vous les utilisez souvent) empêche les erreurs liées à mal ordonnée les paramètres de la fonction.

  • Scala est intégré dans les collections de la bibliothèque, case de classes et d' val mot-clé. Ils fournissent immuable des collections, des classes et des valeurs, et ainsi de prévenir les bogues liés à la mutation de l'état de quelque chose qui ne devrait pas être modifié.
    - En Java, vous pouvez utiliser la Goyave est immuable collections, mais c'est une 3ème partie lib et pas tout le monde va les utiliser ou de savoir pourquoi les utiliser?
    - En Java, vous pouvez utiliser final SomeType, mais c'est tellement plus que val que je pense que la plupart des gens n'utilisez pas habituellement final variables en Java.

Je me demande si l'élimination/l'atténuation de ces trois sortes de bugs peut effectivement supprimer peut-être 10% - 40% de tous les bugs de vos applications? (Pas plus d'entrées en phase nationale:s! :-)) Peut-être cela seul est une raison suffisante pour écrire votre nouvelle application de la Scala à la place?

Je suppose que c'est possible de mettre en place quelque chose de similaire à l'Option/None/Some en Java, mais ce serait dans votre propre application seulement - la Java standard libs et autres 3e partie libs serait encore principalement utiliser null valeurs? Ici (à Quora) plus d'infos sur les différents (fragmentée?) Option/Certains/Aucune des solutions de rechange en Java.

Aussi, Scala: Concis syntaxe -> écrire moins de code -> écrire de moins en moins de bugs :-)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X