Scala代码看起来更简单/更少行的Scala和Java代码示例?

Rom*_*man 92 java comparison language-features scala

我需要Scala和Java代码的一些代码示例(我也非常好奇),它们表明Scala代码比Java编写的代码更简单和简洁(当然两个示例都应该解决同样的问题).

如果只有Scala示例带有注释,例如"这是Scala中的抽象工厂,在Java中看起来会更麻烦",那么这也是可以接受的.

谢谢!

我最喜欢接受和这个答案

Esk*_*ola 75

让我们改进堆栈器的示例并使用Scala的case类:

case class Person(firstName: String, lastName: String)
Run Code Online (Sandbox Code Playgroud)

上面的Scala类包含下面Java类的所有功能,还有一些 - 例如它支持模式匹配(Java没有).Scala 2.8添加了命名和默认参数,这些参数用于为案例类生成复制方法,它提供与以下Java类的with*方法相同的功能.

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 + ")";
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在使用中我们(当然):

Person mr = new Person("Bob", "Dobbelina");
Person miss = new Person("Roberta", "MacSweeney");
Person mrs = miss.withLastName(mr.getLastName());
Run Code Online (Sandbox Code Playgroud)

反对

val mr = Person("Bob", "Dobbelina")
val miss = Person("Roberta", "MacSweeney")
val mrs = miss copy (lastName = mr.lastName)
Run Code Online (Sandbox Code Playgroud)

  • @Bill K:好的,那么我们将有`case class Person(val firstName:String,val lastName:String)`那又怎样?将这件事私有化也是可能的,但没有任何意义,因为不适用等. (7认同)
  • 在2.7.x和2.8.0中,唯一的拳击是在`productElements`和`unapply`中,而不是在构造函数,字段或访问器中:http://gist.github.com/424375 (2认同)
  • 鼓励各种恶作剧/二传手的不良.只有在极不情愿的情况下才能添加塞特斯,只有在必要时才应添加吸气剂.如何添加"简单"会导致不良习惯. (2认同)

sta*_*ker 45

我发现这个令人印象深刻

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

斯卡拉

class Person(val firstName: String, val lastName: String)
Run Code Online (Sandbox Code Playgroud)

除了这些(抱歉没有粘贴,我不想窃取代码)

  • @ abhin4v:是的,但Scala中的代码约定是没有以`get`为前缀的访问器.惯用Java代码与惯用的Scala代码不同.有时用于布尔值的`is`前缀.http://davetron5000.github.com/scala-style/naming_conventions/methods/accessors_mutators.html (7认同)
  • 你可以把它作为`case class`并免费得到`toString`,`equals`和`hashCode`(你也不必显式地生成`val`参数):`case class Person(firstName: String,lastName:String)` (6认同)

mis*_*tor 23

任务:编写程序以索引关键字列表(如书籍).

说明:

  • 输入:List <String>
  • 输出:Map <Character,List <String >>
  • 地图的关键是'A'到'Z'
  • 地图中的每个列表都已排序.

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);         
  }
}
Run Code Online (Sandbox Code Playgroud)

斯卡拉:

object Main extends App {
  val keywords = List("Apple", "Ananas", "Mango", "Banana", "Beer")
  val result = keywords.sorted.groupBy(_.head)
  println(result)
}
Run Code Online (Sandbox Code Playgroud)

  • 使用Java 8,代码几乎与Scalas相同:keywords.stream().sorted().collect(Collectors.groupingBy(it - > it.charAt(0))); 诀窍! (10认同)

mis*_*tor 11

任务:

你有一个包含字段和people类的对象列表.您的任务是首先按此排序此列表,然后按.Personnameagenameage

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());
  }
});
Run Code Online (Sandbox Code Playgroud)

斯卡拉:

val sortedPeople = people.sortBy(p => (p.name, p.age))
Run Code Online (Sandbox Code Playgroud)

更新

自从我写这个答案以来,已经取得了一些进展.Lambdas(以及方法引用)最终落入Java,它们正在风靡Java世界.

这就是上面的代码在Java 8中的表现(由@fredoverflow提供):

people.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
Run Code Online (Sandbox Code Playgroud)

虽然这段代码几乎一样短,但它并不像Scala那样优雅.

Scala中的解决方案,该Seq[A]#sortBy方法接受一个函数A => B,其中B需要一个Ordering.Ordering是一个类型.充分考虑两个世界:比如Comparable,它隐含于所讨论的类型,但是Comparator,它是可扩展的,并且可以追溯地添加到没有它的类型中.由于Java缺少类型类,因此它必须复制每个这样的方法,一次用于Comparable,然后用于Comparator.例如,请参阅comparingthenComparing 此处.

类型类允许人们编写规则,例如"如果A有订单而B有订购,那么他们的元组(A,B)也有订购".在代码中,即:

implicit def pairOrdering[A : Ordering, B : Ordering]: Ordering[(A, B)] = // impl
Run Code Online (Sandbox Code Playgroud)

这就是sortBy我们的代码可以通过名称然后按年龄进行比较的方式.这些语义将使用上述"规则"进行编码.Scala程序员会直观地期望这样做.没有comparing必要添加的特殊用途方法Ordering.

Lambdas和方法参考只是函数式编程的冰山一角.:)


Ben*_*rdy 10

要根据字符串执行的操作的映射.

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");
Run Code Online (Sandbox Code Playgroud)

斯卡拉:

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

这一切都以最好的口味完成!

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();
Run Code Online (Sandbox Code Playgroud)

  • 可以更短:`val defaultFun = {()=> println("找不到任务")}; todos.getOrElse("hi",defaultFun).apply()` (3认同)
  • 甚至更短:`val todos = Map("hi" - > {()=> println("早上好!")})withDefaultValue {()=> println("task not found")}`然后`todos( "喜")()` (2认同)

mis*_*tor 10

任务:

你有一个XML文件"company.xml",如下所示:

<?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>
Run Code Online (Sandbox Code Playgroud)

你要读取这个文件并打印firstNamelastName全体员工的领域.


Java: [取自此处 ]

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();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)



斯卡拉: [从这里拍摄,幻灯片#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)
        } 
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

[比尔编辑; 检查讨论的评论] -

嗯,如何做到这一点,而无需在未格式化的回复部分回复... Hmph.我想我会编辑你的答案,如果它让你烦恼就让你删除它.

这就是我用Java做的更好的库:

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]);
    }
} 
Run Code Online (Sandbox Code Playgroud)

这只是一个快速入侵,不涉及任何魔法和所有可重用的组件.如果我想添加一些魔法,我可以做一些比返回一个字符串数组更好的东西,但即便如此,这个GoodXMLLib也可以完全重用.scanFor的第一个参数是该部分,所有未来的参数都是要查找的有限的项目,但是可以稍微修改界面以添加多个匹配级别而没有真正的问题.

我承认Java总体上有一些非常糟糕的库支持,但是来吧 - 比较Java十年(?)旧XML库的可怕用法和基于简洁的实现是不公平的 - 并且远远不够从语言的比较!

  • 编写Java代码完全是为了解析该特定XML文件而不尝试重用和大量重复代码.无论是谁写的都是故意看起来他不懂编码或者不懂编码. (5认同)

Mik*_*Hay 8

我现在正在斯卡拉写一个二十一点游戏.以下是我的dealerWins方法在Java中的表现:

boolean dealerWins() {
    for(Player player : players)
        if (player.beats(dealer))
            return false;
    return true;
}
Run Code Online (Sandbox Code Playgroud)

以下是它在Scala中的外观:

def dealerWins = !(players.exists(_.beats(dealer)))
Run Code Online (Sandbox Code Playgroud)

万岁的高阶函数!

Java 8解决方案:

boolean dealerWins() {
    return players.stream().noneMatch(player -> player.beats(dealer));
}
Run Code Online (Sandbox Code Playgroud)


Arj*_*ijl 7

我喜欢这个简单的排序和转换示例,取自David Pollak的"Beginning 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)))
Run Code Online (Sandbox Code Playgroud)

在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)
Run Code Online (Sandbox Code Playgroud)


Don*_*zie 6

Quicksort怎么样?


Java的

以下是通过谷歌搜索找到的java示例,

该URL是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
}
Run Code Online (Sandbox Code Playgroud)

斯卡拉

快速尝试Scala版本.代码改进者的开放季节; @)

def qsort(l: List[Int]): List[Int] = {
  l match {
    case Nil         => Nil
    case pivot::tail => qsort(tail.filter(_ < pivot)) ::: pivot :: qsort(tail.filter(_ >= pivot))
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 它也不是尾递归,因此不适合作为高性能算法(或不会溢出堆栈的算法) (3认同)
  • Quicksort在功能列表上不是*O(n ^ 2)*,但肯定有这种危险.渐近地,它仍然是平均值*O(n log n)*,但是有一个更高的统计概率击中最坏情况*O(n ^ 2)*因为我们总是选择列表头部的枢轴点,而不是随意选择一个. (2认同)

use*_*own 6

我喜欢getOrElseUpdate方法,在mutableMap中找到并在这里显示,第一个Java,没有:

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;
}
Run Code Online (Sandbox Code Playgroud)

是的 - 一个WordCount,这里是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
}
Run Code Online (Sandbox Code Playgroud)

这里是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;
}
Run Code Online (Sandbox Code Playgroud)

如果你想100%功能:

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);
}
Run Code Online (Sandbox Code Playgroud)

filter并且sort已经显示,但看看它们与地图的集成有多容易:

    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)
    } 
Run Code Online (Sandbox Code Playgroud)


Dan*_*ral 6

我非常喜欢用户未知的 答案,我将尝试改进它.下面的代码不是 Java示例的直接转换,但它使用相同的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)
}
Run Code Online (Sandbox Code Playgroud)


Tho*_*mas 5

这是一个非常简单的例子:方形整数然后添加它们


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

在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)
Run Code Online (Sandbox Code Playgroud)

精简映射将函数应用于数组的所有元素,因此:

Array(1,2,3).map(square)
Array[Int] = Array(1, 4, 9)
Run Code Online (Sandbox Code Playgroud)

向左折叠将以0作为累加器开始并应用于add(s,i)数组的所有元素(i),以便:

 Array(1,4,9).foldLeft(0)(add)  // return 14 form 0 + 1 + 4 + 9
Run Code Online (Sandbox Code Playgroud)

现在可以进一步压缩到:

Array(1,2,3).map(x => x * x ).foldLeft(0)((s,i) => s + i )
Run Code Online (Sandbox Code Playgroud)

这个我不会尝试使用Java(要做很多工作),将XML转换为Map:


<a>
   <b id="a10">Scala</b>
   <b id="b20">rules</b>
</a>
Run Code Online (Sandbox Code Playgroud)

另一个从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)
Run Code Online (Sandbox Code Playgroud)

  • scala> 1到10 map(x => x*x)sum res0:Int = 385让我们看看那个神秘的java开发人员调用.在那一刻,它的手指在耳边说nah-nah-nah. (5认同)
  • @Jesper对于非Java开发人员来说,Java看起来像是大量的样板和线路噪声.这并不意味着你无法用语言完成真正的工作. (3认同)

Vas*_*iuk 5

问题:您需要设计一个异步执行任何给定代码的方法.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
            }
});
Run Code Online (Sandbox Code Playgroud)

Scala中的相同内容(使用actor):

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    
}
Run Code Online (Sandbox Code Playgroud)

  • 从2.8开始,这可以写成Futures.future {body}并且实际上更强大,因为可以将此返回的未来连接起来以获得它最终评估的值. (6认同)