programing

Scala 코드가 단순해 보이는/줄 수가 적은 Scala 및 Java 코드 샘플?

javaba 2022. 12. 25. 10:49
반응형

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필요한 것은,OrderingOrdering을 사용하다가장 잘해라: "예"와 같은 것: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 코드의 예를 몇 가지 보여주는 문서를 준비하고 있습니다.

Scala : 더 나은 Java

뭔가 덧붙이고 싶은 것이 있으면, 코멘트로 회답해 주세요.

느슨하게 평가된 무한 스트림이 좋은 예입니다.

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

반응형