Exemples de code Scala et Java où le code Scala semble plus simple / a moins de lignes?

j'ai besoin de quelques exemples de code (et je suis aussi vraiment curieux à leur sujet) de code Scala et Java qui montrent que le code Scala est plus simple et concis que le code écrit en Java (bien sûr les deux exemples devraient résoudre le même problème).

S'il n'y a que Scala sample avec des commentaires du genre" ceci est abstract factory en Scala, en Java cela paraîtra beaucoup plus encombrant " alors cela est aussi acceptable.

Merci!

j'aime le plus tous acceptés et ce réponses

91
demandé sur Community 2010-06-01 23:37:15

18 réponses

améliorons exemple de stacker et utilisez les "classes de cas de Scala :

case class Person(firstName: String, lastName: String)

la classe Scala ci - dessus contient toutes les caractéristiques de la classe Java ci-dessous, et un peu plus - par exemple, il soutient correspondance de modèle (que Java n'a pas). Scala 2.8 Ajoute les arguments named et default, qui sont utilisés pour générer une méthode de copie pour case classes, qui donne la même capacité que les méthodes with* de la classe Java suivante.

public class Person implements Serializable {
    private final String firstName;
    private final String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public Person withFirstName(String firstName) {
        return new Person(firstName, lastName);
    }

    public Person withLastName(String lastName) {
        return new Person(firstName, lastName);
    }

    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Person person = (Person) o;
        if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) {
            return false;
        }
        if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) {
            return false;
        }
        return true;
    }

    public int hashCode() {
        int result = firstName != null ? firstName.hashCode() : 0;
        result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
        return result;
    }

    public String toString() {
        return "Person(" + firstName + "," + lastName + ")";
    }
}

ensuite, dans l'usage nous avons (bien sûr):

Person mr = new Person("Bob", "Dobbelina");
Person miss = new Person("Roberta", "MacSweeney");
Person mrs = miss.withLastName(mr.getLastName());

contre

val mr = Person("Bob", "Dobbelina")
val miss = Person("Roberta", "MacSweeney")
val mrs = miss copy (lastName = mr.lastName)
74
répondu Esko Luontola 2017-05-23 12:09:14

j'ai trouvé celui-ci impressionnant

Java

public class Person {
    private final String firstName;
    private final String lastName;
    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    public String getFirstName() {
        return firstName;
    }
    public String getLastName() {
        return lastName;
    }
}

Scala

class Person(val firstName: String, val lastName: String)

ainsi que ceux-ci (désolé de ne pas coller, Je ne voulais pas voler le code)

45
répondu stacker 2010-06-01 19:43:17

tâche: Écrire un programme pour indexer une liste de mots clés (comme des livres).

explication:

  • Entrée: List
  • Sortie: Carte < Character, List>
  • la clé de la carte est' A 'à' Z '
  • chaque liste dans la carte est triée.

Java:

import java.util.*;

class Main {
  public static void main(String[] args) {
    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);         
  }
}

Scala:

object Main extends App {
  val keywords = List("Apple", "Ananas", "Mango", "Banana", "Beer")
  val result = keywords.sorted.groupBy(_.head)
  println(result)
}
23
répondu missingfaktor 2012-09-10 16:47:34

tâche:

vous avez une liste people d'objets de la classe Person qui a les champs name et age . Votre tâche est de trier cette liste par name , et puis age .

Java 7:

Collections.sort(people, new Comparator<Person>() {
  public int compare(Person a, Person b) {
    return a.getName().compare(b.getName());
  }
});
Collections.sort(people, new Comparator<Person>() {
  public int compare(Person a, Person b) {
    return Integer.valueOf(a.getAge()).compare(b.getAge());
  }
});

Scala:

val sortedPeople = people.sortBy(p => (p.name, p.age))

mise à jour

depuis que j'ai écrit cette réponse, il y a eu beaucoup de progrès. Les lambdas (et les références de méthode)ont finalement atterri en Java, et ils prennent le monde de Java par la tempête.

voici à quoi ressemblera le code ci-dessus avec Java 8 (contribution de @fredoverlow):

people.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));

bien que ce code soit presque aussi court, il ne fonctionne pas aussi élégamment que le Scala.

en solution Scala, la méthode Seq[A]#sortBy accepte une fonction A => BB est requis pour ont an Ordering . Ordering est une classe de type. Pensez Meilleur des deux mondes: comme Comparable , il est implicite pour le type en question , mais comme Comparator , il est extensible et peut être ajouté rétrospectivement aux types qui ne l'ont pas. Comme Java n'a pas de classes de type, il doit dupliquer toutes ces méthodes, une fois pour Comparable puis pour Comparator . Par exemple, voir comparing et thenComparing ici .

les classes de type permettent d'écrire des règles telles que "si A A la commande et B la commande, alors leur tuple (A, B) a aussi la commande". En code, c'est-à-dire:

implicit def pairOrdering[A : Ordering, B : Ordering]: Ordering[(A, B)] = // impl

c'est ainsi que sortBy dans notre code peut se comparer par le nom et puis par l'âge. Ceux sémantique sera codé avec la "règle". Un programmeur aurait Scala attendez que cela fonctionne de cette façon. Aucune méthode particulière telle que comparing n'a dû être ajoutée à Ordering .

Lambdas and method references ne sont que la pointe d'un iceberg qui est la programmation fonctionnelle. :)

11
répondu missingfaktor 2015-06-28 12:11:40

tâche:

vous avez un fichier XML" société.xml" qui ressemble à ceci:

<?xml version="1.0"?>
<company>
    <employee>
        <firstname>Tom</firstname>
        <lastname>Cruise</lastname>
    </employee>
    <employee>
        <firstname>Paul</firstname>
        <lastname>Enderson</lastname>
    </employee>
    <employee>
        <firstname>George</firstname>
        <lastname>Bush</lastname>
    </employee>
</company>

vous devez lire ce fichier et imprimer les zones firstName et lastName de tous les employés.





Java: [ tiré de ici ]

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XmlReader {
  public static void main(String[] args) {   
    try {
      File file = new File("company.xml");
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse(file);
      doc.getDocumentElement().normalize();
      NodeList nodeLst = doc.getElementsByTagName("employee");
      for (int s = 0; s < nodeLst.getLength(); s++) {  
        Node fstNode = nodeLst.item(s); 
        if (fstNode.getNodeType() == Node.ELEMENT_NODE) {         
          Element fstElmnt = (Element) fstNode;
          NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("firstname");
          Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
          NodeList fstNm = fstNmElmnt.getChildNodes();
          System.out.println("First Name: "  + ((Node) fstNm.item(0)).getNodeValue());
          NodeList lstNmElmntLst = fstElmnt.getElementsByTagName("lastname");
          Element lstNmElmnt = (Element) lstNmElmntLst.item(0);
          NodeList lstNm = lstNmElmnt.getChildNodes();
          System.out.println("Last Name: " + ((Node) lstNm.item(0)).getNodeValue());
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}





Scala: [tiré de ici , diapositive #19]

import xml.XML

object XmlReader {
  def main(args: Array[String]): Unit = {
    XML.loadFile("company.xml") match {
      case <employee> { employees @ _* } </employee> => {
        for(e <- employees) {
          println("First Name: " + (e \ "firstname").text)
          println("Last Name: " + (e \ "lastname").text)
        } 
      }
    }
  }
}

[ modifier par Bill; vérifier les commentaires pour la discussion] --

Hmm, comment le faire sans répondre dans une section de réponse non formatée... Hmph. Je suppose que je vais modifier ta réponse et te laisser la supprimer si elle te dérange.

C'est comment j'allais le faire en Java avec de meilleures bibliothèques:

public scanForEmployees(String filename) {
    GoodXMLLib source=new GoodXMLLib(filename);
    while( String[] employee: source.scanFor("employee", "firstname", "lastname") )
    {
          System.out.println("First Name: " + employee[0]);
          System.out.println("Last Name: " + employee[1]);
    }
} 

c'est juste un piratage rapide impliquant pas de magie et tous les composants réutilisables. Si je voulais ajouter un peu de magie, je pourrais faire quelque chose de mieux que de retourner un tableau de tableaux de cordes, mais même comme C'est le cas, ce GoodXMLLib serait complètement réutilisable. Le premier paramètre de scanFor est la section, tous les paramètres futurs seraient les éléments à trouver qui est limité, mais l'interface peut être légèrement tamponné pour ajouter plusieurs niveaux de correspondance sans problème réel.

j'admets que Java a un support de bibliothèque assez pauvre en général,mais allez -- pour comparer une utilisation horrible de la décennie de Java(?) une ancienne bibliothèque XML à une implémentation basée sur la terse n'est pas juste--et est loin d'être une comparaison des langues!

10
répondu missingfaktor 2010-09-06 19:06:51

une carte des actions à effectuer en fonction d'une chaîne.

Java 7:

// strategy pattern = syntactic cruft resulting from lack of closures
public interface Todo {   
  public void perform();
}

final Map<String, Todo> todos = new HashMap<String,Todo>();
todos.put("hi", new Todo() { 
    public void perform() { 
        System.out.println("Good morning!");
    } 
} );

final Todo todo = todos.get("hi");
if (todo != null)
    todo.perform();
else
    System.out.println("task not found");

Scala:

val todos = Map( "hi" -> { () => println("Good morning!") } )
val defaultFun = () => println("task not found")
todos.getOrElse("hi", defaultFun).apply()

Et tout est fait dans les meilleures goût!

Java 8:

Map<String, Runnable> todos = new HashMap<>();
todos.put("hi", () -> System.out.println("Good morning!"));
Runnable defaultFun = () -> System.out.println("task not found");
todos.getOrDefault("hi", defaultFun).run();
8
répondu Ben Hardy 2014-07-18 21:41:42

j'ai aimé ce simple exemple de tri et de transformation, tiré du livre' Beginning Scala 'de David Pollak:

En Scala:

def validByAge(in: List[Person]) = in.filter(_.valid).sortBy(_.age).map(_.first)
case class Person(val first: String, val last: String, val age: Int) {def valid: Boolean = age > 18}
validByAge(List(Person("John", "Valid", 32), Person("John", "Invalid", 17), Person("OtherJohn", "Valid", 19)))

En Java:

public static List<String> validByAge(List<Person> in) {
   List<Person> people = new ArrayList<Person>();
   for (Person p: in) {
     if (p.valid()) people.add(p);
   }
   Collections.sort(people, new Comparator<Person>() {
      public int compare(Person a, Person b) {
        return a.age() - b.age();
      } 
   } );
   List<String> ret = new ArrayList<String>();
     for (Person p: people) {
       ret.add(p.first);
     }
   return ret;
}

public class Person {
    private final String firstName;
    private final String lastName;
    private final Integer age;
    public Person(String firstName, String lastName, Integer age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    public String getFirst() {
        return firstName;
    }
    public String getLast() {
        return lastName;
    }
    public Integer getAge() {
       return age;
    }
    public Boolean valid() {
       return age > 18;
    }
}

List<Person> input = new ArrayList<Person>();
input.add(new Person("John", "Valid", 32));
input.add(new Person("John", "InValid", 17));
input.add(new Person("OtherJohn", "Valid", 19));

List<Person> output = validByAge(input)
7
répondu Arjan Blokzijl 2012-07-06 10:40:22

j'écris un jeu de Blackjack à Scala maintenant. Voici comment ma méthode dealerWins ressemblerait en Java:

boolean dealerWins() {
    for(Player player : players)
        if (player.beats(dealer))
            return false;
    return true;
}

Voici à quoi il ressemble en Scala:

def dealerWins = !(players.exists(_.beats(dealer)))

Hourra pour les fonctions d'ordre supérieur!

solution Java 8:

boolean dealerWins() {
    return players.stream().noneMatch(player -> player.beats(dealer));
}
7
répondu MikeFHay 2014-07-18 21:16:51

j'ai aimé utilisateur inconnu réponse tellement je vais essayer de l'améliorer. Le code ci-dessous est pas une traduction directe de L'exemple Java, mais il accomplit la même tâche avec la même API.

def wordCount (sc: Scanner, delimiter: String) = {
  val it = new Iterator[String] {
    def next = sc.nextLine()
    def hasNext = sc.hasNextLine()
  }
  val words = it flatMap (_ split delimiter iterator)
  words.toTraversable groupBy identity mapValues (_.size)
}
6
répondu Daniel C. Sobral 2017-05-23 12:32:02

j'aime beaucoup la méthode getOrElseUpdate, trouvée dans mutablmap et montrée ici, D'abord Java, sans:

public static Map <String, Integer> wordCount (Scanner sc, String delimiters) {
    Map <String, Integer> dict = new HashMap <String, Integer> ();
            while (sc.hasNextLine ()) {
                    String[] words = sc.nextLine ().split (delimiters);
                    for (String word: words) {
                        if (dict.containsKey (word)) {
                            int count = dict.get (word);
                            dict.put (word, count + 1);
                        } else
                            dict.put (word, 1);
                    }
            }       
    return dict;
}

oui - nombre de mots, et ici en scala:

def wordCount (sc: Scanner, delimiter: String) = {
        val dict = new scala.collection.mutable.HashMap [String, Int]()
        while (sc.hasNextLine ()) {
                val words = sc.nextLine.split (delimiter)
                words.foreach (word =>
                      dict.update (word, dict.getOrElseUpdate (word, 0) + 1))
        }
        dict
}

et voici en Java 8:

public static Map<String, Integer> wordCount(Scanner sc, String delimiters)
{
    Map<String, Integer> dict = new HashMap<>();
    while (sc.hasNextLine())
    {
        String[] words = sc.nextLine().split(delimiters);
        Stream.of(words).forEach(word -> dict.merge(word, 1, Integer::sum));
    }
    return dict;
}

et si vous voulez aller 100% fonctionnel:

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.*;

public static Map<String, Long> wordCount(Scanner sc, String delimiters)
{
    Stream<String> stream = stream(sc.useDelimiter(delimiters));
    return stream.collect(groupingBy(identity(), counting()));
}

public static <T> Stream<T> stream(Iterator<T> iterator)
{
    Spliterator<T> spliterator = Spliterators.spliteratorUnknownSize(iterator, 0);
    return StreamSupport.stream(spliterator, false);
}

filter et sort ont déjà été indiqué, mais regardez comme c'est facile, ils sont intégrés à la carte:

    def filterKeywords (sc: Scanner, keywords: List[String]) = {
            val dict = wordCount (sc, "[^A-Za-z]")
            dict.filter (e => keywords.contains (e._1)).toList . sort (_._2 < _._2)
    } 
6
répondu user unknown 2014-07-18 22:51:29

c'est un exemple très simple: entiers carrés et puis les ajouter


    public int sumSquare(int[] list) {
        int s = 0;
        for(int i = 0; i < list.length; i++) {
            s += list[i] * list[i]; 
        }
        return s;
    }

En scala:


val ar = Array(1,2,3)
def square(x:Int) = x * x
def add(s:Int,i:Int) = s+i

ar.map(square).foldLeft(0)(add)

Compact map applique la fonction à tous les éléments du tableau:

Array(1,2,3).map(square)
Array[Int] = Array(1, 4, 9)

Fold left is commencera avec 0 comme l'accumulateur (s) et appliquera add(s,i) à tous les éléments (i) du réseau, de sorte que:

 Array(1,4,9).foldLeft(0)(add)  // return 14 form 0 + 1 + 4 + 9

maintenant, cela peut être compacté à nouveau à:

Array(1,2,3).map(x => x * x ).foldLeft(0)((s,i) => s + i )

celui-ci je ne vais pas essayer en Java (à beaucoup de travail), tourner XML à une carte:


<a>
   <b id="a10">Scala</b>
   <b id="b20">rules</b>
</a>

un autre liner pour obtenir la carte à partir du XML:


val xml = <a><b id="a10">Scala</b><b id="b20">rules</b></a>

val map = xml.child.map( n => (n \ "@id").text -> n.child.text).toMap
// Just to dump it.
for( (k,v) <- map) println(k + " --> " + v)
5
répondu Thomas 2010-06-01 21:10:00

et Quicksort?


Java

ce qui suit est un exemple java trouvé via une recherche google,

L'URL est http://www.mycstutorials.com/articles/sorting/quicksort

public void quickSort(int array[]) 
// pre: array is full, all elements are non-null integers
// post: the array is sorted in ascending order
{
   quickSort(array, 0, array.length - 1);   // quicksort all the elements in the array
}


public void quickSort(int array[], int start, int end)
{
   int i = start;      // index of left-to-right scan
   int k = end;        // index of right-to-left scan

   if (end - start >= 1)               // check that there are at least two elements to sort
   {
       int pivot = array[start];       // set the pivot as the first element in the partition

       while (k > i)                   // while the scan indices from left and right have not met,
       {
           while (array[i] <= pivot && i <= end && k > i) // from the left, look for the first
              i++;                                        // element greater than the pivot
           while (array[k] > pivot && k >= start && k >= i) // from the right, look for the first
              k--;                                          // element not greater than the pivot
           if (k > i)                  // if the left seekindex is still smaller than
               swap(array, i, k);      // the right index, swap the corresponding elements
       }
       swap(array, start, k);          // after the indices have crossed, swap the last element in
                                       // the left partition with the pivot 
       quickSort(array, start, k - 1); // quicksort the left partition
       quickSort(array, k + 1, end);   // quicksort the right partition
    }
    else // if there is only one element in the partition, do not do any sorting
    {
        return;                        // the array is sorted, so exit
    }
}

public void swap(int array[], int index1, int index2) 
// pre: array is full and index1, index2 < array.length
// post: the values at indices 1 and 2 have been swapped
{
   int temp      = array[index1];      // store the first value in a temp
   array[index1] = array[index2];      // copy the value of the second into the first
   array[index2] = temp;               // copy the value of the temp into the second
}

Scala

Une rapide tentative de Scala version. Saison ouverte pour les améliorateurs de code ;@)

def qsort(l: List[Int]): List[Int] = {
  l match {
    case Nil         => Nil
    case pivot::tail => qsort(tail.filter(_ < pivot)) ::: pivot :: qsort(tail.filter(_ >= pivot))
  }
}
5
répondu Don Mackenzie 2010-06-01 22:47:26

problème: vous devez concevoir une méthode qui exécutera n'importe quel code asynchrone donné.



Solution dans Java :

/**
* This method fires runnables asynchronously
*/
void execAsync(Runnable runnable){
    Executor executor = new Executor() {
        public void execute(Runnable r) {
            new Thread(r).start();
        }
    };
    executor.execute(runnable);
}

...

execAsync(new Runnable() {
            public void run() {
                ...   // put here the code, that need to be executed asynchronously
            }
});

La même chose Scala (avec des acteurs):

def execAsync(body: => Unit): Unit = {
  case object ExecAsync    
  actor {
    start; this ! ExecAsync
    loop {
      react {           
        case ExecAsync => body; stop
      }
    }
  }    
}

...

execAsync{  // expressive syntax - don't need to create anonymous classes
  ...  // put here the code, that need to be executed asynchronously    
}
5
répondu Vasil Remeniuk 2010-06-02 11:11:19

the Circuit Breaker pattern from la version de Michael Nygard in FaKods ( lien vers le code )

la mise en œuvre ressemble à ceci dans Scala:

. . .
addCircuitBreaker("test", CircuitBreakerConfiguration(100,10))
. . .


class Test extends UsingCircuitBreaker {
  def myMethodWorkingFine = {
    withCircuitBreaker("test") {
      . . .
    }
  }

  def myMethodDoingWrong = {
    withCircuitBreaker("test") {
      require(false,"FUBAR!!!")
    }
  }
}

que je trouve super sympa. Il semble juste comme un pice de la langue, mais il est un simple mixin dans le CircuitBreaker objet faire tout le travail.

/**
 * Basic MixIn for using CircuitBreaker Scope method
 *
 * @author Christopher Schmidt
 */
trait UsingCircuitBreaker {
  def withCircuitBreaker[T](name: String)(f: => T): T = {
    CircuitBreaker(name).invoke(f)
  }
}

référence dans les autres langues Google pour" disjoncteur " + votre langue.

3
répondu oluies 2010-06-04 21:23:49

Pourquoi personne n'a posté ceci avant:

Java:

class Hello {
     public static void main( String [] args ) {
          System.out.println("Hello world");
     }
}

116 caractères.

Scala:

object Hello extends App {
     println("Hello world")
}

56 caractères.

2
répondu OscarRyz 2012-07-06 10:49:38

je suis en train de préparer un document qui donne plusieurs exemples de code Java et Scala, en utilisant seulement les caractéristiques simples à comprendre de Scala:

Scala : Une meilleure Java

Si vous voulez m'ajouter quelque chose, merci de répondre dans les commentaires.

2
répondu HRJ 2012-09-13 17:33:23

les cours d'eau infinis évalués par la suite sont un bon exemple:

object Main extends Application {

   def from(n: Int): Stream[Int] = Stream.cons(n, from(n + 1))

   def sieve(s: Stream[Int]): Stream[Int] =
     Stream.cons(s.head, sieve(s.tail filter { _ % s.head != 0 }))

   def primes = sieve(from(2))

   primes take 10 print

}

Voici une question qui concerne les flux infinis en Java: est-ce qu'un itérateur infini est une mauvaise conception?

un autre bon exemple sont les fonctions de première classe et les fermetures:

scala> def f1(w:Double) = (d:Double) => math.sin(d) * w
f1: (w: Double)(Double) => Double

scala> def f2(w:Double, q:Double) = (d:Double) => d * q * w
f2: (w: Double,q: Double)(Double) => Double

scala> val l = List(f1(3.0), f2(4.0, 0.5))
l: List[(Double) => Double] = List(<function1>, <function1>)

scala> l.map(_(2))
res0: List[Double] = List(2.727892280477045, 4.0)

Java ne supporte pas les fonctions de première classe, et imiter des fermetures avec des classes internes anonymes n'est pas très élégant. Une autre chose que ce l'exemple montre que java ne peut pas faire exécute du code à partir d'un interpréteur/REPL. Je trouve cela extrêmement utile pour tester rapidement des extraits de code.

1
répondu dbyrne 2017-05-23 12:00:13

ce code Scala...

def partition[T](items: List[T], p: (T, T) => Boolean): List[List[T]] = {
  items.foldRight[List[List[T]]](Nil)((item: T, items: List[List[T]]) => items match {
    case (first :: rest) :: last if p (first, item) =>
      (List(item)) :: (first :: rest) :: last
    case (first :: rest) :: last =>
      (item :: first :: rest) :: last
    case _ => List(List(item))
  })
}

...serait complètement illisible en Java, si possible du tout.

0
répondu JUST MY correct OPINION 2010-06-02 14:14:17