как работать с классом case более 22 полей в scala 2.10.5 [duplicate]

«Явный» тип в Java - это класс, который является неэквивалентным и имеет дело с «сырыми» объектами, а не с типичными типами типовых параметров.

Например, до того, как были доступны дженерики Java , вы должны использовать класс коллекции следующим образом:

LinkedList list = new LinkedList();
list.add(new MyObject());
MyObject myObject = (MyObject)list.get(0);

Когда вы добавляете свой объект в список, ему все равно, какой тип объекта он есть, и когда вы его получите из списка, вам нужно явно указать его на тот тип, который вы ожидаете.

Используя generics, вы удаляете «неизвестный» коэффициент, потому что вы должны явно указать, какой тип объектов может идти в списке:

LinkedList<MyObject> list = new LinkedList<MyObject>();
list.add(new MyObject());
MyObject myObject = list.get(0);

Обратите внимание, что с помощью дженериков вам не нужно бросать объект, исходящий из вызова get, сбор предварительно задан для работы с MyObject. Этот факт является основным движущим фактором для генериков. Он меняет источник ошибок времени выполнения во что-то, что можно проверить во время компиляции.

39
задан Phil 28 November 2013 в 07:32
поделиться

5 ответов

Совсем недавно (октябрь 2016 года, через шесть лет после OP) сообщение в блоге « Scala и 22 » из Ричарда Даллауэя исследует этот предел:

< blockquote>

Еще в 2014 году, когда была выпущена Scala 2.11, было устранено важное ограничение:

Case classes with > 22 parameters are now allowed. 

Это может заставить вас подумать, что нет 22 ограничений в Скала, но это не так. Ограничение сохраняется в функциях и кортежах.

Исправление ( PR 2305 ), введенное в Scala 2.11, устранило ограничение для вышеуказанных общих сценариев: построение классов case, доступа к полю (включая копирование) и сопоставление с образцом ( базирующие крайние случаи ).

Это делалось, опуская unapply и tupled для классов case выше 22 полей. Другими словами, предел Function22 и Tuple22 все еще существует.

Работа над пределом (post Scala 2.11)

Существует два распространенных способа обхода этого предела.

  • Первое - использовать вложенные кортежи. Хотя верно, что кортеж не может содержать более 22 элементов, каждый элемент может быть кортежем
  • . Другим распространенным трюком является использование гетерогенных списков (HLists), где нет 22 предела.

Если вы хотите использовать классы case, вам может быть лучше использовать бесформенную реализацию HList. Мы создали библиотеку Slickless , чтобы сделать это проще. В частности недавний mappedWith метод преобразуется между бесформенными HLists и классами case. Это выглядит так:

import slick.driver.H2Driver.api._
import shapeless._
import slickless._

class LargeTable(tag: Tag) extends Table[Large](tag, "large") {
  def a = column[Int]("a")
  def b = column[Int]("b")
  def c = column[Int]("c")
  /* etc */
  def u = column[Int]("u")
  def v = column[Int]("v")
  def w = column[Int]("w")

  def * = (a :: b :: c :: /* etc */ :: u :: v :: w :: HNil)
    .mappedWith(Generic[Large])
}

В базе данных Slickless имеется полный пример с 26 столбцами .

30
ответ дан VonC 20 August 2018 в 17:54
поделиться

Этот вопрос будет исправлен в Scala 2.11.

30
ответ дан Brian 20 August 2018 в 17:54
поделиться

Когда у вас есть много значений, это обычно признак того, что ваш дизайн нуждается в повторной обработке.

Формируйте прерывистые классы case, которые затем объединяются в более крупные. Это также упрощает понимание кода, обоснование и поддержку кода. Как и в обход этой проблемы у вас есть.

Например, если бы я хотел хранить пользовательские данные, я мог бы это сделать ....

case class User(name: Name, email: String)
case class Name(first: String, last: String)

С таким количеством вещей, это, конечно, не было бы необходимо. Но если у вас есть 22 вещи, которые вы пытаетесь втиснуть в один класс, вы все равно захотите сделать такой класс прерывистого случая.

-4
ответ дан Dante Romero 20 August 2018 в 17:54
поделиться
  • 1
    Существует один json, который должен быть проанализирован, который содержит более 22 полей. Используя сопоставление объектов, например json4s, для него требуется класс со всеми полями. – Sohaib 9 July 2015 в 09:53
  • 2
    – Dragonborn 31 August 2018 в 17:23

Создайте нормальный класс, который действует как класс case.

Я все еще использую scala 2.10.X, так как это последнее, поддерживаемое Spark, а в Spark-SQL я сильно использую классы case.

Обходной путь для case classes с более чем 22 полями:

class Demo(val field1: String,
    val field2: Int,
    // .. and so on ..
    val field23: String)

extends Product 
//For Spark it has to be Serializable
with Serializable {
    def canEqual(that: Any) = that.isInstanceOf[Demo]

    def productArity = 23 // number of columns

    def productElement(idx: Int) = idx match {
        case 0 => field1
        case 1 => field2
        // .. and so on ..
        case 22 => field23
    }
}
21
ответ дан Teodor-Bogdan Barbieru 20 August 2018 в 17:54
поделиться
  • 1
    Расширение продукта дает вам хорошие части итераций, но вы не получаете метод копирования. Метод копирования относится к классам классов, но не к признаку Product, потому что он генерируется компилятором Scala (теперь его можно строго ввести для каждого поля в вашем классе case). – Samer Adra 27 May 2016 в 14:11
  • 2
    Какой сериализатор вы регистрируете в Spark? Я начал с twitter.chill.avro.AvroSerializer.SpecificRecordBinarySerializer, но в этом случае мой класс должен реализовывать SpecificRecordBase, что снова ставит меня против предела поля 22. – Stuart 20 July 2016 в 20:21

Интересно, что ваш конструктор загружен, но вы можете упаковать связанные значения в собственный класс case.

Так что, хотя у вас может быть

case class MyClass(street: String, city: String, state: String, zip: Integer)

, вы можете сделать это

case class MyClass(address: Address)

У вас есть и другие опции:

  • Элементы группы в кортежи
  • Создайте свой собственный признак Function23 (или что-то еще)
  • Использовать currying

UPDATE: Как уже отмечали другие, это уже не проблема после выпуска Scala 2.11 - хотя я бы не решайтесь использовать термин «исправить». Тем не менее, «Catch 22», если хотите, иногда появляется в сторонних библиотеках Scala.

17
ответ дан Vidya 20 August 2018 в 17:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: