Scala 코드가 단순해 보이는/줄 수가 적은 Scala 및 Java 코드 샘플?
스칼라 코드와 자바 코드가 자바어로 작성된 코드보다 간단하고 간결하다는 것을 보여주는 스칼라 코드 샘플이 필요합니다(물론 두 샘플 모두 같은 문제를 해결할 수 있습니다.
"이것은 Scala의 추상 공장입니다. Java의 경우 훨씬 더 번거로워 보일 것입니다."와 같은 코멘트가 있는 Scala 샘플만 있다면 이 또한 허용됩니다.
감사합니다!
나는 모든 것을 받아들이는 것을 가장 좋아한다. 그리고
스태커의 예를 개선하고 Scala의 사례 클래스를 사용합니다.
case class Person(firstName: String, lastName: String)
위의 Scala 클래스는 아래 Java 클래스의 모든 기능을 포함하며, 예를 들어 패턴 매칭을 지원합니다(Java에는 없음).Scala 2.8에는 named 인수와 default 인수가 추가되어 있습니다.이 인수는 케이스 클래스의 복사 메서드를 생성하는데 사용됩니다.이 메서드는 다음 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)
이번 건은 인상적이었어요
자바
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)
이것들과 함께 (붙여넣지 않아 미안, 코드를 훔치고 싶지 않았어)
과제: 키워드 목록(책 등)을 색인화하는 프로그램을 작성합니다.
설명:
- 입력: 리스트 <String>
- 출력: 맵 <문자, 리스트>
- 지도의 키는 'A'부터 'Z'까지입니다.
- 지도의 각 목록이 정렬됩니다.
자바:
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);
}
}
스칼라:
object Main extends App {
val keywords = List("Apple", "Ananas", "Mango", "Banana", "Beer")
val result = keywords.sorted.groupBy(_.head)
println(result)
}
작업:
.people
Person
" " " 가 .name
★★★★★★★★★★★★★★★★★」age
이 이 과제입니다.name
, 그리고 다음으로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());
}
});
스칼라:
val sortedPeople = people.sortBy(p => (p.name, p.age))
갱신하다
제가 이 답변을 쓴 이후, 꽤 진척이 있었습니다.람다(및 메서드 참조)가 마침내 Java에 상륙하여 Java 세계를 사로잡고 있습니다.
Java 8에서는 위의 코드가 다음과 같습니다(@fredoverflow에 의해 설명됨).
people.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
이 코드는 거의 짧지만 Scala만큼 우아하게 동작하지는 않습니다.
에서 Scala는Seq[A]#sortBy
.A => B
서 ''는B
필요한 것은,Ordering
Ordering
을 사용하다가장 잘해라: "예"와 같은 것:Comparable
이지만, 를 들어 '어느 쪽인가'와 같은 표현입니다Comparator
확장 가능하며, 확장성이 없는 유형에 소급하여 추가할 수 있습니다.없기 의 경우 .Comparable
에 대해서는, 럼음음음 음음 ,Comparator
를 들어, 「 」, 「 」를 해 주세요.comparing
★★★★★★★★★★★★★★★★★」thenComparing
여기 있습니다.
유형 클래스에서는 "A가 주문하고 B가 주문하면 해당 튜플(A, B)도 주문"과 같은 규칙을 작성할 수 있습니다.코드에서는 다음과 같습니다.
implicit def pairOrdering[A : Ordering, B : Ordering]: Ordering[(A, B)] = // impl
해서 렇게는sortBy
이름, 나이 순으로 비교할 수 있습니다.이러한 의미론은 위의 "규칙"으로 인코딩됩니다.Scala 프로그래머라면 직감적으로 이렇게 동작할 것으로 예상합니다..comparing
하지 않으면 안 되었다Ordering
.
람다와 메서드 참조는 기능적 프로그래밍인 빙산의 일각에 불과합니다.:)
작업:
다음과 같은 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>
합니다.firstName
★★★★★★★★★★★★★★★★★」lastName
모든 직원의 분야
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();
}
}
}
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]);
}
}
이것은 마법이나 재사용 가능한 모든 컴포넌트를 수반하지 않는 간단한 해킹입니다.매직을 추가하고 싶다면 문자열 어레이를 반환하는 것보다 더 나은 작업을 수행할 수 있지만, 이 GoodXMLib는 완전히 재사용할 수 있습니다.scanFor의 첫 번째 파라미터는 섹션입니다.앞으로 검출되는 파라미터는 모두 제한이 있는 항목이지만 인터페이스를 약간 버퍼링하여 여러 레벨의 매칭을 추가할 수 있기 때문에 문제가 없습니다.
Java는 일반적으로 라이브러리의 지원이 매우 부족하다는 것은 인정합니다만, 자바의 10년(?) 전의 XML 라이브러리의 끔찍한 사용을 간결함을 바탕으로 한 구현과 비교하는 것은 공평하지 않습니다.또한 언어 비교와는 거리가 먼 것입니다.
문자열에 따라 수행할 작업 맵입니다.
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");
스칼라:
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();
나는 데이비드 폴락의 '스칼라 시작' 책에서 따온 간단한 분류와 변환 예를 좋아했다.
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)))
자바어:
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에서의 deler Wins 메서드는 다음과 같습니다.
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));
}
퀵소트는 어때?
자바
다음은 구글 검색을 통해 발견된 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))
}
}
사용자 미지의 답변이 너무 마음에 들어서 개선하려고 합니다.아래 코드는 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)
}
저는 getOrElseUpdate 메서드를 매우 좋아합니다.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;
}
예 - WordCount, 여기 스칼라:
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)
}
이것은 매우 간단한 예입니다. 정사각형 정수를 더한 다음 더합니다.
public int sumSquare(int[] list) {
int s = 0;
for(int i = 0; i < list.length; i++) {
s += list[i] * list[i];
}
return s;
}
스칼라:
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을 맵으로 변환합니다.
<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)
문제: 주어진 코드를 비동기적으로 실행하는 메서드를 설계해야 합니다.
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
}
});
스칼라(배우 사용):
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
}
Michael Nygard's Release It in FaKods의 서킷 브레이커 패턴(코드 링크)
scala에서는 다음과 같이 구현됩니다.
. . .
addCircuitBreaker("test", CircuitBreakerConfiguration(100,10))
. . .
class Test extends UsingCircuitBreaker {
def myMethodWorkingFine = {
withCircuitBreaker("test") {
. . .
}
}
def myMethodDoingWrong = {
withCircuitBreaker("test") {
require(false,"FUBAR!!!")
}
}
}
정말 좋은 것 같아요언어의 핵심처럼 보이지만 CircuitBreaker Object에서 모든 작업을 수행하는 단순한 혼합입니다.
/**
* 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에서 "Circuit breaker" + 해당 언어를 참조하십시오.
Scala의 간단한 기능만을 사용하여 Java와 Scala 코드의 예를 몇 가지 보여주는 문서를 준비하고 있습니다.
뭔가 덧붙이고 싶은 것이 있으면, 코멘트로 회답해 주세요.
느슨하게 평가된 무한 스트림이 좋은 예입니다.
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에서 코드를 실행할 수 없음을 나타냅니다.코드 스니펫을 빠르게 테스트하는 데 매우 유용하다고 생각합니다.
이전에 이 글을 올리지 않은 이유:
자바:
class Hello {
public static void main( String [] args ) {
System.out.println("Hello world");
}
}
116자
스칼라:
object Hello extends App {
println("Hello world")
}
56글자
이 스칼라 코드...
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))
})
}
가능하다면 자바에서는 전혀 읽을 수 없습니다.
언급URL : https://stackoverflow.com/questions/2952732/samples-of-scala-and-java-code-where-scala-code-looks-simpler-has-fewer-lines
'programing' 카테고리의 다른 글
Workbench를 사용하여 서버에서 데이터베이스의 ER 모델을 가져오는 방법 (0) | 2022.12.25 |
---|---|
선택한 색인으로 MySQL에 임시 테이블 만들기 (0) | 2022.12.25 |
MariaDB의 have_ssl이 DISABLE인 채로 Debian 및 YaSSL에서 SSL을 활성화할 수 없습니다. (0) | 2022.12.25 |
프라이머리 키는 MySQL에서 자동으로 인덱싱됩니까? (0) | 2022.12.25 |
파일이 존재하지 않으면 Python의 open()은 파일을 생성하지 않습니다. (0) | 2022.12.25 |