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


94

我需要一些Scala和Java代码的代码示例(并且我也对此感到很好奇),这些示例表明Scala代码比用Java编写的代码更简单,简洁(当然,两个示例都应该解决相同的问题)。

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

谢谢!

我最喜欢的所有接受和这个答案


3
稍作努力,您可能会在rosettacode.org上
nicerobot 2010年

4
这种问题怎么会有一个正确答案?
polygenelubricants 2010年

@polygenelubricants:你有什么建议?
罗曼(Roman)2010年

10
@罗马:我们希望Scala更加简洁。如果您能找到用Java比Scala更简洁地表达的内容,那将更加有趣。
兰德尔·舒尔茨

1
@Randall Schulz:每个人都知道Scala更加简洁,但有时出于学术目的,我们需要使用示例和背景理论进行证明。
罗曼2010年

Answers:


76

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

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

上面的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 + ")";
    }
}

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

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

反对

val mr = Person("Bob", "Dobbelina")
val miss = Person("Roberta", "MacSweeney")
val mrs = miss copy (lastName = mr.lastName)

2
在2.7.x和2.8.0唯一的拳击是在productElementsunapply,而不是在构造函数中,场,或访问:gist.github.com/424375
返璞词

2
鼓励各种各样的吸气剂/涂胶剂不良。仅在极不情愿的情况下添加设置器,仅在必要时添加添加器。添加“简单性”如何导致不良习惯的一个很好的例子。
比尔K

7
@Bill K:好的,那我们有 case class Person(val firstName: String, val lastName: String) 什么呢?使那件事私人将是可能的也是如此,但并没有任何意义,因为不应用等
SOC

1
@shiva case class Person(private val firstName: String),但是您不应该使用案例类。相反,这样做class Person(firstName: String)firstName默认为私有。
nilskp 2013年

1
@shiva否。val和之间的区别private val是访问器方法(即firstName()firstName(String))是公共的还是私有的。在Scala中,字段始终是私有的。为了使Scala生成Java风格的get / set方法(除了Scala风格的访问器),还有@BeanProperty注释。
Esko Luontola 2013年

45

我发现这令人印象深刻

爪哇

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;
    }
}

斯卡拉

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

以及这些(对不起,我不想窃取代码)


此scala代码将不会生成getFirstNamegetLastName方法。您必须使用批注对参数进行scala.reflect.BeanProperty批注。
Abhinav Sarkar 2010年

7
@ abhin4v:是的,但是Scala中的代码约定是不要以开头的访问器get。惯用的Java代码与惯用的Scala代码不同。有时,is前缀用于布尔值。davetron5000.github.com/scala-style/naming_conventions/methods/...
艾司科Luontola

6
你可以做一个case class,并得到toStringequalshashCode免费(你也不必使论点val明确):case class Person(firstName: String, lastName: String)
加斯帕

@shiva,因为case class,不只是class
nilskp 2013年

23

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

说明:

  • 输入:List <String>
  • 输出:Map <字符,列表<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);         
  }
}

Scala:

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

您可以使用v.sorted代替(v sortBy identity)。
Eastsun'6

1
在Scala 2.8中,您可以使用mapValues(_.sorted)代替map {case ...}
Alex Boisvert 2010年

10
在Java 8中,代码几乎与Scalas相同:keyword.stream()。sorted()。collect(Collectors.groupingBy(it-> it.charAt(0))); 绝招!
协调员

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());
  }
});

Scala:

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

更新资料

自从我写了这个答案以来,已经取得了很大的进步。lambda(和方法引用)终于进入了Java,并且席卷了Java世界。

这是上面的代码在Java 8中的样子(由@fredoverflow提供):

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

虽然这段代码几乎很短,但是却不能像Scala那样优雅地工作。

在Scala解决方案中,该Seq[A]#sortBy方法A => BB需要具有的地方接受一个函数OrderingOrdering是类型类。最好两全其美:就像Comparable,对于所讨论的类型是隐式的,但是像一样Comparator,它是可扩展的,可以追溯地添加到没有它的类型中。由于Java缺少类型类,因此它必须重复每个这样的方法,一次是Comparable,然后是Comparator。例如,请参见comparingthenComparing 此处

类型类允许编写规则,例如“如果A具有排序而B具有排序,则它们的元组(A,B)也具有排序”。在代码中,即:

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

这就是sortBy我们的代码中可以按名称然后按年龄进行比较的方式。这些语义将使用上述“规则”进行编码。一个Scala程序员会直观地期望这种方式可以工作。无需comparing添加任何特殊目的的方法Ordering

Lambda和方法引用只是函数式编程的冰山一角。:)


缺少lambda(或至少是方法引用)是我在Java中缺少的最重要功能。
Petr Gladkikh

@fredoverflow感谢您添加Java 8示例。它仍然说明了Scala的方法为何优越。稍后再添加。
missingfaktor 2015年

@rakemous,队友,答案是六年多以前写的。
missingfaktor

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>

您必须阅读此文件并打印所有员工的firstNamelastName字段。


爪哇: [从这里获得 ]

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: [取自此处,幻灯片#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)
        } 
      }
    }
  }
}

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

嗯,如何在不格式化的回复部分中不回复的情况下完成该操作...嗯。我想我会编辑您的答案,如果让您感到烦恼,可以删除它。

这就是我在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]);
    }
} 

这只是一个快速的技巧,不涉及任何魔术和所有可重用的组件。如果我想添加一些魔术,我可以做的比返回字符串数组的数组更好,但是即使这样,GoodXMLLib还是可以完全重用的。scanFor的第一个参数是该部分,所有将来的参数将是要查找的项目,但有一定限制,但是可以对界面进行轻微的抛光以添加多个级别的匹配,而没有任何实际问题。

我会承认Java通常在某些方面对库的支持很差,但是请继续-将Java十年(?)的旧XML库的可怕用法与基于简洁的实现进行比较是不公平的,而且还很遥远。比较语言!


嗯,使用SAX或StAX解析器可以使Java示例更短,更好看。但是SCALA仍然是一个非常不错的选择
oluies,2010年

5
编写Java代码就是为了解析该特定XML文件而编写的,无需尝试重​​用,并且有很多重复的代码。不管是谁写的,要么是故意让他看起来不懂编码,要么就是不懂编码。
Bill K

@Bill K:我从未在Java中完成过XML解析,因此我从某个随机站点中选择了此示例。我不介意随意编辑答案的Java部分。
missingfaktor

好吧,让我们假设您是在说语言差异,而不是库差异。在这种情况下,两者几乎是相同的。第二个示例中唯一的语言差异是匹配/大小写情况,如果由库以这种方式实现,则可以在一行中将其作为for循环来完成。
Bill K

@比尔·K:不,你完全错了。这里有两个功能非常强大的Scala功能:1. XML文字2.模式匹配。Java没有任何一个。因此,用某种假设的库编写的等效Java代码肯定不会完全相同。(尝试写作,您会知道的。)
missingfaktor 2010年

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");

Scala:

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

所有这些都以最佳的口味完成!

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();

@Rahul G,我认为您的编辑不正确。todos.get("hi")返回Option[()=>Unit]正确匹配所需的值。
huynhjl 2010年

@huynhjl,我不好。回滚。
missingfaktor 2010年

3
甚至可以更短:val defaultFun = {() => println("task not found")}; todos.getOrElse("hi", defaultFun).apply()
Geoff Reedy

2
甚至更短:val todos = Map("hi" -> { () => println("Good morning!") }) withDefaultValue { () => println("task not found") }然后todos("hi")()
Martin Ring

8

我现在正在Scala中编写二十一点游戏。这是我的DealerWins方法在Java中的外观:

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

这是在Scala中的外观:

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

万岁,高阶函数!

Java 8解决方案:

boolean dealerWins() {
    return players.stream().noneMatch(player -> player.beats(dealer));
}

scala的语法非常困难。需要记住很多:-(
AZ_

Scala就像CSS,要记住许多属性和属性
AZ_12年

1
更好:def dealerWins = !(players exists (_ beats dealer))
Kevin Wright 2012年

7

我喜欢这个简单的排序和转换示例,摘自David Pollak的“ Beginning Scala”一书:

在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)))

在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)

6

Quicksort怎么样?


爪哇

以下是通过Google搜索找到的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
}

斯卡拉

快速尝试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))
  }
}

1
链表上的快速排序是否具有O(n ^ 2)时间复杂度?通常将mergesort或类似名称用于链接列表。
Esko Luontola 2010年

3
它也不是尾递归的,因此不适合用作高性能算法(或不会溢出堆栈的算法)
oxbow_lakes 2010年

感谢您的有用评论。我曾经在某处看到quicksort这样写的内容,它的紧凑性给我留下了深刻的印象,显然我没有给予太多考虑。LOC比较让我很吃惊,这在Scala v Java中总是很诱人。
唐·麦肯齐

2
Quicksort 在功能列表上不是O(n ^ 2),但是肯定有危险。渐近地,它仍然是平均值O(n log n),但是达到最坏情况O(n ^ 2)的统计概率更高,因为我们总是选择列表顶部的枢轴点,而不是随机选择一个。
Daniel Spiewak 2010年

过滤两次是不好的。请参阅我对您的问题的回答partition,以免发生这种情况。
Daniel C. Sobral 2010年

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)
}

我目前尚未安装scala-2.8来测试此代码段,但我想我可以看到意图是什么-根本不使用“关键字”。它会生成所有弦乐及其频率的映射,不是吗?
用户未知

@user是的,它就是这样做的。这不是您的代码完成的吗?哦,我明白了。我复制了错误的行。我现在要修复它。:-)
Daniel C. Sobral 2010年

6

我非常喜欢在mutableMap中找到的getOrElseUpdate方法,这里显示的是第一个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;
}

是的-一个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
}

在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;
}

如果您想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);
}

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)
    } 

我非常喜欢这个例子。它避免了比较案例类的简便方法,并且不会出现显示Scala代码而不是Java等效代码的错误。
Daniel C. Sobral

5

这是一个非常简单的示例:平方整数,然后将它们相加


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

在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)

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

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

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

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

现在,可以将其进一步压缩为:

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

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


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

另一种从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)

sumSquare在Scala中遇到的问题是,对于Java开发人员而言,它看起来非常神秘,这会使他们感到不满,因为他们抱怨Scala晦涩而复杂…………
Jesper 2010年

我重新格式化以改进示例。希望这不会伤害Scala。
托马斯

5
scala> 1到10映射(x => x * x)总和res0:Int = 385让我们看一下java开发人员所说的神秘方法。那时手指在耳边说“ nah-nah-nah”。
psp 2010年

3
@Jesper对于非Java开发人员来说,Java看起来像大量样板和线路噪音。这并不意味着您无法使用该语言完成真正的工作。
James Moore

您可以使用reduceLeft(add)而不是foldLeft(0)(add)。我认为当您的开始元素是组的零/身份元素时,阅读起来会更容易。
Debilski 2010年

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
            }
});

Scala中的同一件事(使用演员):

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    
}

6
从2.8开始,它可以写为Futures.future {body},实际上功能更强大,因为可以将由此返回的未来结合起来以获得最终评估的价值。
戴夫·格里菲斯

3

来自Michael NygardFaKods中的Release It的Circuit Breaker模式 (链接到代码

在Scala中,实现如下所示:

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


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

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

我认为这是超级好。它看起来只是该语言的一小部分,但它是CircuitBreaker对象中的一个简单混合函数,可以完成所有工作。

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

使用其他语言的Google参考“断路器” +您的语言。


3

我正在准备一个文档,其中提供了几个Java和Scala代码示例,仅利用了易于理解的Scala功能:

Scala:更好的Java

如果您希望我添加一些内容,请在评论中回复。


标题“ Scala:一个更好的Java”误导人
duckhunt


1

惰性计算的无限流是一个很好的例子:

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

}

这是一个解决Java中无限流的问题: 无限迭代器设计不好吗?

另一个很好的例子是一流的函数和闭包:

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不支持一流的功能,并且用匿名内部类模仿闭包并不是很优雅。此示例表明Java不能执行的另一件事是从解释器/ REPL运行代码。我发现这对于快速测试代码段非常有用。


请注意,筛子太慢,无法实用。
Elazar Leibovich

@oxbow_lakes这些示例没有等效的java。
dbyrne 2010年

@dbyme不正确。您可以轻松地将Java子类化IterableIterator生成无限流。
Daniel C. Sobral

@dbyrne“此示例表明Java不能做的另一件事是从解释器/ REPL运行代码。我发现这对于快速测试代码段非常有用。” 我在Eclipse中使用剪贴簿页面尝试Java代码段。如果不是在所有Java中都能完成大部分Java工作,则不需要REPL。在我不确定语言或库功能的早期,我使用了notepad.exe和javac,并且在很短的时间内运行得非常好且很快-尽管REPL易于使用-而且速度更快。我可以通过安装我们已经安装的VisualAge来完全避免记事本被黑客入侵

0

此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))
  })
}

...如果可能的话,在Java中将是完全不可读的。


10
我的正确的OPINIO:感谢您的回答!但您能解释一下发生了什么吗?我还不熟悉Scala语法,并且(这就是为什么这样)的原因,即使对于我来说,它也似乎完全不可读。
罗曼(Roman)2010年

它使用提供的分区功能作为case语句的模式匹配子句中的防护来对类型T的通用列表进行分区。
我的正确观点2010年

3
奇怪的。我什至不是遥不可及的Scala专家,而且可以弄清楚这一点。
只是我的正确观点2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.