Samples of Scala and Java code where Scala code looks simpler/has fewer lines?
我需要一些Scala和Java代码的代码示例(我也很好奇),它们显示Scala代码更简单简洁,然后用Java编写代码(当然两个示例都应该解决同样的问题)。
如果只有Scala样的评论,比如"这是在斯卡拉的抽象工厂,在Java中它看起来会更麻烦",那么这也是可以接受的。
谢谢!
我最喜欢被接受的答案
让我们改进Stacker的示例并使用scala的case类:
上面的Scala类包含下面的Java类的所有特性,还有一些,例如,它支持模式匹配(Java没有这样的模式)。Scala 2.8添加了命名和默认参数,这些参数用于生成CASE类的复制方法,提供与下面Java类的方法相同的能力。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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 +")"; } } |
。
然后,在使用中我们有(当然):
1 2 3 | Person mr = new Person("Bob","Dobbelina"); Person miss = new Person("Roberta","MacSweeney"); Person mrs = miss.withLastName(mr.getLastName()); |
。
反对
1 2 3 | val mr = Person("Bob","Dobbelina") val miss = Person("Roberta","MacSweeney") val mrs = miss copy (lastName = mr.lastName) |
我觉得这个令人印象深刻
爪哇
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
斯卡拉
号
还有这些(不好意思没有粘贴,我不想偷代码)
- 皇后问题
- 皇后区问题斯卡拉
任务:编写一个程序来索引关键字列表(如书籍)。
说明:
- 输入:list
- 输出:map
> - 地图的关键是"a"到"z"
- 对地图中的每个列表进行排序。
爪哇:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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); } } |
号
斯卡拉:
1 2 3 4 5 | object Main extends App { val keywords = List("Apple","Ananas","Mango","Banana","Beer") val result = keywords.sorted.groupBy(_.head) println(result) } |
号
任务:
您有一个包含字段
Java 7:
1 2 3 4 5 6 7 8 9 10 | 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()); } }); |
号
斯卡拉:
1 | val sortedPeople = people.sortBy(p => (p.name, p.age)) |
号更新
自从我写下这个答案以来,已经有了很大的进步。LAMBDAS(和方法参考)终于登陆爪哇,他们正在攻占爪哇世界。
这是上面代码与Java 8(由@ FrdodoFLUW提供的)类似的代码:
1 |
号
虽然这段代码几乎和scala代码一样短,但它的工作却没有scala代码那么优雅。
在scala解决方案中,
类型类允许我们编写规则,比如"如果a有排序,b有排序,那么它们的元组(a,b)也有排序"。在代码中,即:
1 | implicit def pairOrdering[A : Ordering, B : Ordering]: Ordering[(A, B)] = // impl |
号
这就是我们代码中的
lambda和方法引用只是函数式编程的冰山一角。:)
任务:
您有一个XML文件"company.xml",它如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0"?> <company> <firstname>Tom</firstname> <lastname>Cruise</lastname> </employee> <firstname>Paul</firstname> <lastname>Enderson</lastname> </employee> <firstname>George</firstname> <lastname>Bush</lastname> </employee> </company> |
您必须阅读此文件并打印所有员工的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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(); } } } |
号
斯卡拉:【从这里开始,幻灯片19】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[按比尔编辑;检查讨论的评论]--
嗯,如何不在未格式化的回复部分进行回复…嗯。我想我会编辑你的答案,让你删除它,如果它困扰你。
这就是我如何在Java中使用更好的库:
1 2 3 4 5 6 7 8 |
。
这只是一个快速的黑客,不涉及魔术和所有可重用的组件。如果我想添加一些魔力,我可以做一些比返回字符串数组更好的事情,但是即使这个goodxmllib是完全可重用的。scanfor的第一个参数是该部分,所有未来的参数都是要查找的有限项,但是界面可以稍微抛光,以添加多个匹配级别,没有真正的问题。
我承认Java一般有一些很差的库支持,但是来比较一下Java十年的可怕用法(?)旧的XML库对一个基于简洁的实现来说是不公平的——而且远不是语言的比较!
根据字符串执行的操作的映射。
Java 7:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 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"); |
斯卡拉:
1 2 3 | val todos = Map("hi" -> { () => println("Good morning!") } ) val defaultFun = () => println("task not found") todos.getOrElse("hi", defaultFun).apply() |
而且都是以最好的口味做的!
Java 8:
1 2 3 4 |
号
我现在在斯卡拉写21点游戏。下面是我的DealErrWin方法在Java中的用法:
1 2 3 4 5 6 | boolean dealerWins() { for(Player player : players) if (player.beats(dealer)) return false; return true; } |
以下是斯卡拉的情况:
1 | def dealerWins = !(players.exists(_.beats(dealer))) |
号
高次功能万岁!
Java 8解决方案:
1 2 3 | boolean dealerWins() { return players.stream().noneMatch(player -> player.beats(dealer)); } |
我喜欢这个简单的排序和转换示例,摘自大卫·波拉克的《开始的斯卡拉》一书:
在scala中:
1 2 3 |
号
在Java中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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) |
我非常喜欢"未知用户"的答案,所以我会努力改进它。下面的代码不是Java实例的直接翻译,而是用相同的API完成相同的任务。
1 2 3 4 5 6 7 8 |
号
我非常喜欢在MutabLimAP中找到的GETORESeLoad方法,并在这里显示,第一个Java,没有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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; } |
。
是的-一个字数,在scala中:
1 2 3 4 5 6 7 8 9 |
这里是Java 8:
1 2 3 4 5 6 7 8 9 10 |
。
如果你想100%发挥作用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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); } |
1 2 3 4 |
。
快点怎么样?
爪哇下面是通过谷歌搜索找到的Java示例,
网址是http://www.mycstutorials.com/articles/sorting/quicksort
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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版本的快速尝试。代码改进程序的开放季节;@)
1 2 3 4 5 6 |
号
问题:您需要设计一个将异步执行任何给定代码的方法。
Java解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /** * 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中也是这样(使用actors):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 } |
号
这是一个非常简单的例子:平方整数然后相加
1 2 3 4 5 6 7 | public int sumSquare(int[] list) { int s = 0; for(int i = 0; i < list.length; i++) { s += list[i] * list[i]; } return s; } |
。
在scala中:
1 2 3 4 5 | 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) |
紧凑映射将该函数应用于数组的所有元素,因此:
。
fold left将以0作为累加器开始,并将
1 |
号
现在可以进一步压缩到:
1 |
号
这一个我不会在Java中尝试(大量工作),将XML转换成地图:
1 2 | <b id="a10">Scala <b id="b20">rules |
号
另一个从XML获取映射的一行程序:
1 2 3 4 5 | val xml = <b id="a10">Scala<b id="b20">rules val map = xml.child.map( n => (n "@id").text -> n.child.text).toMap // Just to dump it. for( (k,v) <- map) println(k +" -->" + v) |
号
迈克尔·尼加德在法科兹发布的断路器图案(链接到代码)
在scala中实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | . . . addCircuitBreaker("test", CircuitBreakerConfiguration(100,10)) . . . class Test extends UsingCircuitBreaker { def myMethodWorkingFine = { withCircuitBreaker("test") { . . . } } def myMethodDoingWrong = { withCircuitBreaker("test") { require(false,"FUBAR!!!") } } } |
我觉得非常好。它看起来就像一幅语言的图片,但它只是一个简单的电路断路器对象中的混合,可以完成所有工作。
1 2 3 4 5 6 7 8 9 10 | /** * Basic MixIn for using CircuitBreaker Scope method * * @author Christopher Schmidt */ trait UsingCircuitBreaker { def withCircuitBreaker[T](name: String)(f: => T): T = { CircuitBreaker(name).invoke(f) } } |
。
其他语言的参考谷歌"断路器"+你的语言。
为什么以前没人发过这个:
爪哇:
1 2 3 4 5 |
116个字符。
斯卡拉:
1 2 3 | object Hello extends App { println("Hello world") } |
56个字符。
我正在准备一个文档,它给出了Java和Scala代码的几个例子,只使用了简单的理解斯卡拉的特性:
斯卡拉:一个更好的Java
如果您希望我添加一些内容,请在评论中回复。
延迟计算的无限流就是一个很好的例子:
1 2 3 4 5 6 7 8 9 10 11 12 | 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中无限流的问题:无限迭代器是不是坏的设计?
另一个很好的例子是第一类函数和闭包:
1 2 3 4 5 6 7 8 9 10 11 | 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中运行代码。我发现这对于快速测试代码片段非常有用。
这个scala代码…
1 2 3 4 5 6 7 8 9 | 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中是完全不可读的。