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

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

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

감사!

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



답변

스태커의 예제를 개선 하고 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)


답변

이건 인상적 이었어

자바

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)

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


답변

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

설명:

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


답변

직무:

및 필드가 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.

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


답변

직무:

다음과 같은 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 라이브러리의 끔찍한 사용을 간결한 구현을 기반으로 수행 한 구현과 비교하는 것은 공정하지 않습니다. 언어 비교에서!


답변

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

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


답변

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