Вы не можете и не должны полагаться на упорядочение элементов в объекте JSON.
Из спецификации JSON в http://www.json.org/
Объект является неупорядоченным набором пар имя / значение
. Как следствие, библиотеки JSON могут изменять порядок элементов по своему усмотрению. Это не ошибка.
Здесь вы как бы неправильно понимаете вещи,
Итак, допустим, у вас есть x: M[A]
и f: A = N[B]
для любых Monad
, M
и N
, тогда x.flatMap(f)
должно быть таким же, как x.map(f).flatten
.
Но здесь у вас есть своего рода вложенная монада map: M[N[A]]
, и ваша функция - f: A => B
с последующим псевдонимом,
scala> type MapWithStringKey[A] = Map[String, A]
// defined type alias MapWithStringKey
scala> type TupleOfInt = (Int, Int)
// defined type alias TupleOfInt
scala> val map: MapWithStringKey[List[TupleOfInt]] = Map("a" -> List(1 ->11,1->111), "b" -> List(2 -> 22, 2 ->222))
// map: MapWithStringKey[List[TupleOfInt]] = Map(a -> List((1,11), (1,111)), b -> List((2,22), (2,222)))
. Этот случай полностью отличается от упомянутого выше стандартного определения, связывающего [ 1110] до map
и flatten
.
Теперь, это только один из нестандартных случаев, когда вы можете выбрать любой из двух вариантов в зависимости от того, что вы хотите. И когда мы добавим специальные свойства уникальности ключа из Map
(о чем мы уже говорили в ответе @ sepp2k), все становится еще более непредсказуемым.
TL; DR: тип результата обоих вызовов различен. Вызов .map().flatten
возвращает Iterable[(Int, Int)]
, а вызов .flatMap()
возвращает Map[Int, Int]
. Поскольку карта может не содержать один и тот же ключ дважды, первая запись на ключ заменяется второй записью.
Рассмотрим Map
как Iterable[(Key,Value)]
. При вызове .map
вам нужно будет предоставить ему функцию, которая возвращает кортеж, (Key, Value)
(фактические типы могут отличаться от оригинальных Key
и Value
).
В вашем примере, Value
оказывается List[(Int, Int)]
. Когда вы вызываете .map
и возвращаете Value
оригинала Map
, вы в конечном итоге получаете Iterable[List[(Int, Int)]]
, который в результате обращения к .flatten
превращается в Iterable[(Int, Int)]
, объединяя «внутренние» списки вместе. Если бы вы превратили это в карту (вызвав .toMap
), вы бы увидели тот же результат, что и с flatMap
.
Теперь flatMap
отличается тем, что ожидает тип возвращаемого значения Seq[(Key, Value)]
, а не просто (Key, Value)
. Затем он использует возвращенное значение в качестве записей во вновь построенном Map
.
В вашем случае ваш исходный Value
из List[(Int, Int)]
удовлетворяет ожидаемому типу возврата, превращая ваш исходный Map[(String, List[(Int, Int)]
в Map[(Int, Int)]
. Поскольку карта не может содержать две записи с одинаковыми ключами, второе вхождение ключа заменяет более раннее вхождение.
Чтобы увидеть это поведение, полезно использовать REPL (просто запустите scala
) вместо написания основного класса, чтобы вы могли видеть промежуточные значения и их типы.
scala> val theMap = Map("a" -> List(1 ->11,1->111), "b" -> List(2 -> 22, 2 ->222))
theMap: scala.collection.immutable.Map[String,List[(Int, Int)]] = Map(a -> List((1,11), (1,111)), b -> List((2,22), (2,222)))
scala> val mapped = theMap.map(_._2)
mapped: scala.collection.immutable.Iterable[List[(Int, Int)]] = List(List((1,11), (1,111)), List((2,22), (2,222)))
scala> val flattened = mapped.flatten
flattened: scala.collection.immutable.Iterable[(Int, Int)] = List((1,11), (1,111), (2,22), (2,222))
scala> val flatMapped = theMap.flatMap(_._2)
flatMapped: scala.collection.immutable.Map[Int,Int] = Map(1 -> 111, 2 -> 222)
scala> val flattenedToMap = flattened.toMap
flattenedToMap: scala.collection.immutable.Map[Int,Int] = Map(1 -> 111, 2 -> 222)
При вызове .map(f)
для Map
с f
, который возвращает (K, V)
для некоторых K и V (не обязательно тех же типов K и V оригинала Map
), результатом будет Map[K, V]
. В противном случае, если f
возвращает какой-либо другой (не парный) тип T
, результатом будет Iterable[T]
. Так что будет Map
, если функция вернет пару, и Iterable
в противном случае.
В вашем случае функция возвращает List[(Int, Int)]
, поэтому результатом является Iterable[List[(Int, Int)]]
, а не Map. .flatten
затем превращает это в Iterable[(Int, Int)]
.
При непосредственном использовании flatMap
вы напрямую получите пары (Int, Int)
, поэтому результатом будет Map[Int, Int]
, а не Iterable[(Int, Int)]
. И поскольку Map
не допускают дублирования ключей, Map
содержит меньше элементов, чем Iterable
.