Scala 코드가 더 단순 해 보이거나 줄이 더 적은 Scala 및 Java 코드 샘플?


94

Scala 코드가 Java로 작성된 코드보다 더 간단하고 간결하다는 것을 보여주는 Scala 및 Java 코드의 일부 코드 샘플이 필요합니다 (물론 두 샘플 모두 동일한 문제를 해결해야 함).

"이것은 Scala의 추상 팩토리입니다. Java에서는 훨씬 더 번거롭게 보일 것입니다"와 같은 주석이있는 Scala 샘플 만있는 경우에도 허용됩니다.

감사!

나는 대부분의 수락을 좋아 하고이 답변


3
약간의 노력으로 rosettacode.org
nicerobot

4
이런 종류의 질문에 어떻게 하나의 정답이있을 수 있습니까?
polygenelubricants 2010 년

@polygenelubricants : 그리고 당신이 제안하는 것은 무엇입니까?
Roman

10
@Roman : 우리는 Scala가 더 간결 할 것으로 기대합니다. Scala보다 Java로 더 간결하게 표현 된 것을 찾을 수 있다면 더 흥미로울 것입니다.
Randall Schulz

1
@Randall Schulz : 누구나 Scala가 더 간결하다는 것을 알고 있지만 때로는 학문적 목적에서 예제와 배경 이론이있는 증거가 필요합니다.
Roman

답변:


76

스태커의 예제를 개선 하고 Scala의 케이스 클래스를 사용 합시다 .

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

스칼라 클래스 위는 자바 아래 클래스의 모든 기능을 포함, 몇 가지 더 - 예를 들면가 지원하는 패턴 매칭을 (자바하지 않습니다). 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
retronym

2
모든 종류의 게터 / 세터 불량을 조장합니다. 세터는 극도로 꺼려서만 추가해야하며, 게터는 필요한 경우에만 추가해야합니다. "단순함"을 추가하는 것이 나쁜 습관으로 이어지는 좋은 예입니다.
Bill 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

1
@shiva 번호의 차이 valprivate 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)

뿐만 아니라 (붙여 넣지 않아서 죄송합니다. 코드를 훔치고 싶지 않았습니다)


이 스칼라 코드는 getFirstNamegetLastName메서드를 생성하지 않습니다 . 이를 위해 매개 변수에 scala.reflect.BeanProperty주석을 달아야합니다.
Abhinav Sarkar

7
@ abhin4v : 예,하지만 Scala의 코드 규칙은 접두사가 get. 관용적 Java 코드는 관용적 Scala 코드와 다릅니다. 때로는 is접두어는 논리 값에 사용됩니다. davetron5000.github.com/scala-style/naming_conventions/methods/…
Esko Luontola 2010-06-01

6
당신은 그것을 만들고 , 그리고 무료로 case class얻을 수 있습니다 (그리고 당신은 또한 명시 적으로 논쟁을 할 필요가 없습니다 ) :toStringequalshashCodevalcase class Person(firstName: String, lastName: String)
Jesper

@shiva, 대한 case class, 아니 단지 class.
nilskp

23

과제 : 책과 같은 키워드 목록을 색인화하는 프로그램을 작성하십시오.

설명:

  • 입력 : 목록 <문자열>
  • 출력 : Map <Character, List <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)
}

(v sortBy identity) 대신 v.sorted를 사용할 수 있습니다.
Eastsun

1
그리고 Scala 2.8에서는 map {case ...} 대신 mapValues ​​(_. sorted)를 사용할 수 있습니다.
Alex Boisvert

10
Java 8에서 코드는 Scalas와 거의 동일합니다. keyword.stream (). sorted (). collect (Collectors.groupingBy (it-> it.charAt (0))); 트릭을 수행합니다!
The Coordinator

11

직무:

및 필드가 people있는 클래스의 객체 목록 Person이 있습니다 . 이 목록을 먼저별로 정렬 한 다음별로 정렬해야합니다 .nameagenameage

자바 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만큼 우아하게 작동하지는 않습니다.

스칼라 용액에서, Seq[A]#sortBy방법은 기능을 허용 할 필요가 있다 를 . 유형 클래스입니다. 두 세계 모두를 가장 잘 생각하십시오. 예를 들어 , 문제의 유형에 대해 암시 적이지만 , 확장 가능하고없는 유형에 소급 적으로 추가 할 수 있습니다. Java에는 유형 클래스가 없기 때문에 이러한 모든 메서드 를 . 예를 들어 및 여기를 참조 하십시오 .A => BBOrderingOrderingComparableComparatorComparableComparatorcomparingthenComparing

유형 클래스를 사용하면 "A에 순서가 있고 B에 순서가 있으면 튜플 (A, B)에도 순서가 있습니다."와 같은 규칙을 작성할 수 있습니다. 코드에서는 다음과 같습니다.

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

이것이 sortBy우리 코드에서 이름과 나이를 비교 하는 방법 입니다. 이러한 의미는 위의 "규칙"으로 인코딩됩니다. Scala 프로그래머는 이것이 이런 식으로 작동 할 것이라고 직관적으로 예상 할 것입니다. 와 같은 특수 목적 방법 comparing을에 추가 할 필요가 없습니다 Ordering.

람다와 메서드 참조는 함수형 프로그래밍 인 빙산의 일각에 불과합니다. :)


누락 된 람다 (또는 적어도 메소드 참조)는 내가 Java에서 놓친 가장 중요한 기능입니다.
Petr Gladkikh

@fredoverflow Java 8 예제를 추가해 주셔서 감사합니다. Scala의 접근 방식이 우수한 이유를 여전히 보여줍니다. 나중에 더 추가하겠습니다.
missingfaktor 2015-06-09

@rakemous, 친구, 대답은 6 년 전에 작성되었습니다.
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의 10 년 (?) 오래된 XML 라이브러리의 끔찍한 사용을 간결한 구현을 기반으로 수행 한 구현과 비교하는 것은 공정하지 않습니다. 언어 비교에서!


흠, Java 예제는 SAX 또는 StAX 구문 분석기를 사용하면 더 짧고 더 잘 보입니다. 하지만 여전히 SCALA 하나는 정말 좋습니다
oluies 2010-06-04

5
Java 코드는 재사용을 시도하지 않고 많은 중복 코드를 사용하지 않고 특정 XML 파일을 구문 분석하기 위해 정확하게 작성되었습니다. 누구든지 코딩을 이해하지 못하거나 코딩을 이해하지 못하는 것처럼 고의적으로 보이려고 한 것입니다.
Bill K

@Bill K : Java에서 XML 구문 분석을 한 적이 없으므로 임의의 사이트에서이 예제를 선택했습니다. 대답의 Java 부분을 자유롭게 편집하십시오.
missingfaktor 2010

글쎄요, 라이브러리 차이가 아니라 언어 차이를 이야기한다고 가정 해 봅시다.이 경우 둘은 거의 동일 할 것입니다. 두 번째 예제의 유일한 언어 차이점은 라이브러리에서 그렇게 구현 된 경우 for 루프로 한 줄에서 수행 할 수있는 일치 / 대 / 소문자입니다.
Bill K

@Bill K : 아니요, 완전히 틀 렸습니다. 여기에는 매우 강력한 두 가지 Scala 기능이 있습니다. 1. XML 리터럴 2. 패턴 매칭. Java에는 이들 중 하나가 없습니다. 따라서 가상 라이브러리에 작성된 동등한 Java 코드는 동일하지 않습니다. (쓰기를 시도해보십시오. 알 수 있습니다.)
missingfaktor 2010-07-06

10

문자열에 따라 수행 할 작업 맵입니다.

자바 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()

그리고 모든 것이 가능한 최고의 맛으로 이루어집니다!

자바 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-06-03

@huynhjl, 내 나쁜. 롤백했습니다.
missingfaktor 2010-06-03

3
더 짧을 수 있습니다.val defaultFun = {() => println("task not found")}; todos.getOrElse("hi", defaultFun).apply()
Geoff Reedy 2010-06-09

2
더 짧게 : val todos = Map("hi" -> { () => println("Good morning!") }) withDefaultValue { () => println("task not found") }그리고 그 다음todos("hi")()
Martin Ring

8

지금 스칼라로 블랙 잭 게임을 작성하고 있습니다. 여기에 내 DeerWins 메서드가 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));
}

스칼라는 구문이 매우 어렵습니다. 너무 많이 기억해야합니다 :-(
AZ_

Scala는 기억해야 할 많은 속성과 속성에 대해 CSS와 같습니다
AZ_

1
더 나은 :def dealerWins = !(players exists (_ beats dealer))
케빈 라이트

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

자바 :

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

유용한 의견에 감사드립니다. 나는 어딘가에서 이와 같이 쓰여진 퀵소트를 보았고 그것이 콤팩트함에 감명을 받았다. 분명히 나는 ​​그것을 많이 고려하지 않았다. 나는 항상 Scala v Java에서 매혹적인 LOC 비교에 매료되었습니다.
Don Mackenzie

2
Quicksort는 기능 목록에서 O (n ^ 2) 가 아니지만 확실히 위험합니다. 점근 적으로는 여전히 평균 O (n log n) 이지만 , 무작위로 하나를 선택하지 않고 항상 목록의 선두에서 피벗 포인트를 선택하기 때문에 최악의 경우 O (n ^ 2) 에 도달 할 확률이 더 높습니다. .
Daniel Spiewak 2010 년

두 번 필터링하는 것은 좋지 않습니다. 귀하의 질문에 대한 내 대답에서 partition그것을 피하기 위해 사용하십시오 .
Daniel C. Sobral

6

알 수없는 사용자의 답변이 너무 마음에 들었 습니다. 개선을 위해 노력하겠습니다. 아래 코드는 하지 자바 예제를 직접 번역,하지만 같은 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-06-07

6

나는 mutableMap에서 발견되고 여기에 표시된 getOrElseUpdate 메소드를 많이 좋아합니다.

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

이 예를 많이 좋아합니다. 케이스 클래스를 비교하는 쉬운 경로를 피하고 Java와 동등한 코드가 아닌 Scala 코드를 표시하는 실수를하지 않습니다.
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;
    }

스칼라에서 :


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)

sumSquareScala에서 의 문제 는 Java 개발자에게 매우 비밀 스럽기 때문에 Scala가 모호하고 복잡하다고 불평하는 탄약을 줄 것입니다.
Jesper

예제를 개선하기 위해 약간 다시 포맷했습니다. 이것이 스칼라를 해치지 않기를 바랍니다.
Thomas

5
scala> 1 to 10 map (x => x * x) sum res0 : Int = 385 자바 개발자 호출을 살펴 보겠습니다. 그 시점에서 귀에 손가락이 nah-nah-nah라고 말합니다.
psp 2010-06-02

3
@Jesper Java가 아닌 개발자에게 Java는 방대한 양의 상용구와 라인 노이즈처럼 보입니다. 그렇다고 언어로 실제 작업을 수행 할 수 없다는 의미는 아닙니다.
James Moore

foldLeft (0) (add) 대신 reduceLeft (add)를 사용할 수 있습니다. 시작 요소가 그룹의 0 / ID 요소 일 때 읽기가 더 쉽다고 생각합니다.
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}로 작성 될 수 있으며 실제로 반환되는 미래가 결합되어 결국 평가되는 값을 얻을 수 있기 때문에 실제로 더 강력합니다.
Dave Griffith

3

Michael Nygard의 Release It in FaKods ( link to code ) 의 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

저는 Scala의 이해하기 쉬운 기능만을 활용하여 Java 및 Scala 코드의 여러 예제를 제공하는 문서를 준비하고 있습니다.

Scala : 더 나은 자바

추가를 원하시면 댓글에 답장 해주세요.


제목 "스칼라 : 더 나은 자바는"missleading한다
duckhunt

2

이전에 아무도 게시하지 않은 이유 :

자바:

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

116 자

스칼라 :

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

56 자


1
Application고려 유해 ... 특징 부 (trait) scala-blogs.org/2008/07/...
missingfaktor

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는 일급 함수를 지원하지 않으며 익명의 내부 클래스로 클로저를 모방하는 것은 그리 우아하지 않습니다. 이 예제에서 자바가 할 수없는 또 다른 것은 인터프리터 / REPL에서 코드를 실행하는 것입니다. 코드 스 니펫을 빠르게 테스트하는 데 매우 유용합니다.


체가 너무 느려 실용적이지 않습니다.
Elazar Leibovich

@oxbow_lakes이 예제에 해당하는 Java가 없습니다.
dbyrne 2010-06-03

@dbyme 사실이 아닙니다. 당신은 쉽게 자바의 서브 클래스 수 IterableIterator무한 스트림을 생성 할 수 있습니다.
Daniel C. Sobral

@dbyrne "이 예제에서 자바가 할 수없는 또 다른 것은 인터프리터 / REPL에서 코드를 실행하는 것입니다.이 코드는 코드 조각을 빠르게 테스트하는 데 매우 유용합니다." Java 스 니펫을 시도하기 위해 Eclipse에서 스크랩북 페이지를 사용합니다. 대부분의 Java가 해당 IDE에서 작동하지는 않지만 REPL이 필요하지 않습니다. 언어 또는 라이브러리 기능에 대해 확신이 서지 않았던 초기에 notepad.exe와 javac를 사용했고 짧은 시간 후에 매우 잘 작동했습니다. REPL이 다소 사용하기 쉽고 빠릅니다. 우리가 이미 가지고 있던 VisualAge를 설치함으로써 메모장 해킹을 완전히 피할 수있었습니다

0

이 스칼라 코드는 ...

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

... 가능하다면 자바에서는 완전히 읽을 수 없습니다.


10
내 올바른 OPINIO : 답변 감사합니다! 하지만 거기에서 무슨 일이 일어나는지 설명해 주시겠습니까? 나는 아직 Scala 구문에 익숙하지 않으며 (그것이 가능한 이유입니다) 지금도 완전히 읽을 수없는 것처럼 보입니다.
Roman

case 문의 패턴 일치 절에서 제공된 분할 함수를 가드로 사용하여 유형 T의 일반 목록을 분할합니다.
내 올바른 의견입니다.

3
기묘한. 나는 원격으로 Scala 전문가가 아니므로 그것을 알아낼 수 있습니다.
그냥 내 올바른 의견
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.