当前位置:网站首页>Tips and tricks for Scala collections

Tips and tricks for Scala collections

2021-10-22 10:43:44 Bird's nest

Catalog [−]

  1. legend Legend
  2. Combine Composition
  3. side effect Side effects
  4. Sequence
    1. establish Creation
    2. Length
      1. For arrays , priority of use length instead of size.
      2. Don't check empty The property of is reversed
      3. Don't calculate length To check empty
      4. Don't use... Directly length To compare
    3. Equivalent Equality
      1. Do not use == Compare arrays :
      2. Don't check different classifications (categories) The equality of sets of
      3. Do not use sameElements To compare ordered sets
      4. Do not check equality manually
    4. Indexing
      1. Do not use index Get the first element
      2. Do not use index Get the last element
      3. Do not explicitly check index The boundary of the
      4. Don't copy headOption
      5. Don't copy lastOption
      6. look out indexOf and lastIndexOf Parameter type
      7. Do not construct index Of Range
      8. Do not use by hand index Come on zip aggregate
    5. Check the existence of the element Existence
      1. Don't use assertions equality predicate To check for the presence of
      2. look out contains Parameter type
      3. Don't use assertions inequality predicate To check that it doesn't exist
      4. Do not count the number of elements to check for the presence of
      5. Don't use filter To check for the presence of
    6. Filtering
      1. Don't negate assertions
      2. Don't use filter Number of statistical elements
      3. Don't use filter Find the first value of the element
    7. Sorting
      1. Do not manually sort by one attribute
      2. Don't follow by hand identity Sort
      3. One step to complete sorting inversion
    8. Reduction
      1. Don't calculate by hand sum
      2. Don't calculate by hand product
      3. Do not manually search for minimum and maximum values
      4. Don't copy forall
      5. Don't copy exists
    9. Rewriting
      1. Merge successive filter call
      2. Merge successive map call
      3. filter Sort after
      4. Calling map Do not explicitly call invert before reverse
      5. Don't show the inverted iterator
      6. Do not convert a collection to Set Get an unrepeatable set
      7. Don't copy slice
      8. Don't copy splitAt
      9. Don't copy span
      10. Don't copy partition
      11. Don't copy takeRight
      12. Don't copy flatten
      13. Don't copy flatMap
      14. Don't use... When you don't need results map
      15. Do not generate temporary collections
      16. Use the assignment operator
  5. Set
    1. Do not use sameElements Compare unordered sets
    2. Don't calculate the intersection manually
    3. Don't calculate by hand diff
  6. Option
    1. Value
      1. Do not use None and Option Compare
      2. Do not use Some and Option Compare
      3. Do not use instance types to check the existence of values
      4. Do not use pattern matching to check the existence of values
      5. Don't negate the existence checking property
      6. Do not check the existence of the value and then process the value
    2. Null
      1. Don't pass and null Compare to construct Option
      2. Do not display the provided null As an alternative
    3. Rewriting
      1. take map with getOrElse convert to fold
      2. Don't copy exists
      3. Don't put... By hand option convert to sequence
  7. Map
    1. Do not use lift Replace get
    2. Do not call... Separately get and getOrElse
    3. Do not manually extract key sets
    4. Do not manually extract value sets
    5. Careful use filterKeys
    6. Careful use mapValues
    7. Don't do it by hand filter key
    8. Use the assignment operator to reassign
  8. Add

original text : Scala Collections Tips and Tricks,
author Pavel Fatin yes JetBrains An employee of , For artifact IntelliJ IDEA Development Scala plug-in unit .
By its work Scala Collections inspections ) Inspired by the , He sorted out this about Java Collections API A list of tips .
Some techniques are only reflected in some subtle implementation details , But most techniques are common sense , But in most cases, it is ignored .
Tips and techniques for sexual harmony are valuable , Can help you understand Scala Collections, It can be that your code is faster and simpler .

legend Legend

To make the following example easier to understand , Here are some conventions :

  • seq — One Seq-based Set , such as Seq(1, 2, 3)
  • set — One Set example , such as Set(1, 2, 3)
  • array — An array , such as Array(1, 2, 3)
  • option — One Option, such as Some(1)
  • map — One Map, such as Map(1 -> "foo", 2 -> "bar")
  • p — An assertion predicate function , type T => Boolean, such as _ > 2
  • n — An integer
  • i — An index
  • f, g — Simple functions , A => B
  • x, y — Some literal values (arbitrary values)
  • z — Initial value or default value

Combine Composition

remember , Although these techniques are independent and self-contained , We can still combine them and iterate step by step to get a higher-level expression , Take the following example , In a Seq Check whether an element exists in :

       
       
       
1
2
3
4
5
6
7
8
9
       
       
       
seq.filter(_ == x).headOption != None
// Via seq.filter(p).headOption -> seq.find(p)
seq.find(_ == x) != None
// Via option != None -> option.isDefined
seq.find(_ == x).isDefined
// Via seq.find(p).isDefined -> seq.exists(p)
seq.exists(_ == x)
// Via seq.exists(_ == x) -> seq.contains(x)
seq.contains(x)

We can rely on ”substitution model of recipe application“ (SICP)) To simplify complex expressions .

side effect Side effects

”Side effects“ Is a basic concept , There is this concept in functional programming languages . Scala There is one PPT Special introduction : Side-effect checking for Scala
Basically ,”Side effects“ It's such an action , In addition to returning a value , External functions or expressions also observe this action and one of the following behaviors :

  • There are input and output operations ( Such as file , The Internet I/O)
  • Changes to external variables
  • The state of the external object has changed
  • Throw an exception

When a function or expression has any of the above situations , Let's say it has side effects (Side effects), Or we'll say it's " pure " Function or expression of (pure).

side effects What's the big deal ? When there are side effects , The order of calculation cannot be changed arbitrarily . For example, the following two " pure " (pure) expression :

       
       
       
1
2
       
       
       
val x = 1 + 2
val y = 2 + 3

Because they have no side effects , Two expressions can be interchanged , First x after y And first y after x The effect is the same .
If there are side effects ( There is console output ):

       
       
       
1
2
       
       
       
val x = { print( "foo"); 1 + 2 }
val y = { print( "bar"); 2 + 3 }

Two expressions cannot be interchanged , Because once you swap positions , The order of the output results has changed .
So one side effect is to reduce the number of possible conversions (reduces the number of possible transformations), Including possible simplification and optimization .
The same reason applies to Collection Related expressions . Look at an external builder Variable ( Side effects and methods append):

       
       
       
1
       
       
       
seq filter { x => builder.append(x); x > 3 } headOption

In principle, seq.filter(p).headOption It can be simplified as seq.find(p), But side effects prevent us from doing this . If you try to do this :

       
       
       
1
       
       
       
seq find { x => builder.append(x); x > 3 }

The result is different from the previous expression . After the previous expression evaluates, all values greater than 3 All elements have been added to builder It's in , The latter expression finds the first one greater than 3 No more elements will be added .
The two expressions are not equivalent .

Is automatic simplification possible ? Here are two golden rules , It can be used in code with side effects :

  1. Avoid side effects as much as possible
  2. Otherwise, the side effects will be separated from pure code

For the example above , We need to get rid of builder Or isolate it from pure code . in consideration of builder Is the object of a third party , We can't get rid of , Then we do it in isolation :

       
       
       
1
2
       
       
       
seq.foreach(builder.append)
seq.filter(_ > 3).headOption

So we can use the techniques in this article to replace :

       
       
       
1
2
       
       
       
seq.foreach(builder.append)
seq.find(x > 3)

Well done ! Automatic simplification is also possible , An added benefit is due to clear isolation , The code is easier to understand .
A less obvious benefit is , The code becomes more robust . The example above , Side effects target different Seq Realization , The results of side effects are also different , such as Vector and Stream, Side effect isolation allows us to avoid this uncertain behavior .

Sequence

The tips in this section are for Seq And its subclasses , Some transformations can be applied to other collection classes , Such as Set, Option,Map , even to the extent that Iterator class , Because they provide similar interfaces .

establish Creation

Show create collection

       
       
       
1
2
3
4
5
       
       
       
// Before
Seq[T]()
// After
Seq.empty[T]

Sometimes you can save memory ( reusing empty object ) and CPU (length check waste ).

It can also be applied to Set, Option, Map, Iterator.

Length

For arrays , priority of use length instead of size.

       
       
       
1
2
3
4
5
       
       
       
// Before
array.size
// After
array.length

length and size Basically synonymous . stay Scala 2.11 in ,Array.size It is realized by implicit conversion . So every time you call , An intermediate wrapper class will be created , Unless you allow jvm Of escape analysis . This will produce redundant GC object , Affect performance .

Don't check empty The property of is reversed

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
!seq.isEmpty
!seq.nonEmpty
// After
seq.nonEmpty
seq.isEmpty

The same applies Set, Option, Map, Iterator

Don't calculate length To check empty

       
       
       
1
2
3
4
5
6
7
8
9
       
       
       
// Before
seq.length > 0
seq.length != 0
seq.length == 0
// After
seq.nonEmpty
seq.nonEmpty
seq.isEmpty

On the one hand, there have been inspections empty Methods , On the other hand ,, such as LinearSeq And subclasses List, It will cost O(n) The time calculation length(IndexedSeq cost O(1)).

The same applies Set, Map

Don't use... Directly length To compare

       
       
       
1
2
3
4
5
6
7
8
9
10
11
       
       
       
// Before
seq.length > n
seq.length < n
seq.length == n
seq.length != n
// After
seq.lengthCompare(n) > 0
seq.lengthCompare(n) < 0
seq.lengthCompare(n) == 0
seq.lengthCompare(n) != 0

Same as above , Calculation length Sometimes it's very expensive , It is possible to spend from O(length) Reduced to O(length min n).
For infinite stream Come on , The above skills are absolutely necessary .

Equivalent Equality

Do not use == Compare arrays :

       
       
       
1
2
3
4
5
       
       
       
// Before
array1 == array2
// After
array1.sameElements(array2)

because == Just compare instance objects , Not the elements inside .

The same applies Iterator

Don't check different classifications (categories) The equality of sets of

       
       
       
1
2
3
4
5
       
       
       
// Before
seq == set
// After
seq.toSet == set

Do not use sameElements To compare ordered sets

       
       
       
1
2
3
4
5
       
       
       
// Before
seq1.sameElements(seq2)
// After
seq1 == seq2

Do not check equality manually

       
       
       
1
2
3
4
5
       
       
       
// Before
seq1.corresponds(seq2)(_ == _)
// After
seq1 == seq2

Use the built-in method .

Indexing

Do not use index Get the first element

       
       
       
1
2
3
4
5
       
       
       
// Before
seq( 0)
// After
seq.head

Do not use index Get the last element

       
       
       
1
2
3
4
5
       
       
       
// Before
seq(seq.length - 1)
// After
seq.last

Do not explicitly check index The boundary of the

       
       
       
1
2
3
4
5
       
       
       
// Before
if (i < seq.length) Some(seq(i)) else None
// After
seq.lift(i)

Don't copy headOption

       
       
       
1
2
3
4
5
6
       
       
       
// Before
if (seq.nonEmpty) Some(seq.head) else None
seq.lift( 0)
// After
seq.headOption

Don't copy lastOption

       
       
       
1
2
3
4
5
6
       
       
       
// Before
if (seq.nonEmpty) Some(seq.last) else None
seq.lift(seq.length - 1)
// After
seq.lastOption

look out indexOf and lastIndexOf Parameter type

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
Seq( 1, 2, 3).indexOf( "1") // compilable
Seq( 1, 2, 3).lastIndexOf( "2") // compilable
// After
Seq( 1, 2, 3).indexOf( 1)
Seq( 1, 2, 3).lastIndexOf( 2)

Do not construct index Of Range

       
       
       
1
2
3
4
5
       
       
       
// Before
Range( 0, seq.length)
// After
seq.indices

Do not use by hand index Come on zip aggregate

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.zip(seq.indices)
// After
seq.zipWithIndex

Check the existence of the element Existence

Don't use assertions equality predicate To check for the presence of

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.exists(_ == x)
// After
seq.contains(x)

The same applies to Set, Option, Iterator

look out contains Parameter type

       
       
       
1
2
3
4
5
       
       
       
// Before
Seq( 1, 2, 3).contains( "1") // compilable
// After
Seq( 1, 2, 3).contains( 1)

Don't use assertions inequality predicate To check that it doesn't exist

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.forall(_ != x)
// After
!seq.contains(x)

The same applies to Set, Option, Iterator

Do not count the number of elements to check for the presence of

       
       
       
1
2
3
4
5
6
7
8
9
       
       
       
// Before
seq.count(p) > 0
seq.count(p) != 0
seq.count(p) == 0
// After
seq.exists(p)
seq.exists(p)
!seq.exists(p)

The same applies to Set, Map, Iterator

Don't use filter To check for the presence of

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
seq.filter(p).nonEmpty
seq.filter(p).isEmpty
// After
seq.exists(p)
!seq.exists(p)

The same applies to Set, Option, Map, Iterator

Filtering

Don't negate assertions

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.filter(!p)
// After
seq.filterNot(p)

The same applies to Set, Option, Map, Iterator

Don't use filter Number of statistical elements

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.filter(p).length
// After
seq.count(p)

call filter A temporary collection will be generated , influence GC And performance .

The same applies to Set, Option, Map, Iterator

Don't use filter Find the first value of the element

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.filter(p).headOption
// After
seq.find(p)

The same applies to Set, Option, Map, Iterator

Sorting

Do not manually sort by one attribute

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.sortWith(_.property < _.property)
// After
seq.sortBy(_.property)

Don't follow by hand identity Sort

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
seq.sortBy(it => it)
seq.sortBy(identity)
seq.sortWith(_ < _)
// After
seq.sorted

One step to complete sorting inversion

       
       
       
1
2
3
4
5
6
7
8
9
       
       
       
// Before
seq.sorted.reverse
seq.sortBy(_.property).reverse
seq.sortWith(f(_, _)).reverse
// After
seq.sorted(Ordering[T].reverse)
seq.sortBy(_.property)(Ordering[T].reverse)
seq.sortWith(!f(_, _))

Reduction

Don't calculate by hand sum

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
seq.reduce(_ + _)
seq.fold(z)(_ + _)
// After
seq.sum
seq.sum + z

Other possible methods reduceLeft, reduceRight, foldLeft, foldRight

The same applies to Set, Iterator

Don't calculate by hand product

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
seq.reduce(_ * _)
seq.fold(z)(_ * _)
// After
seq.product
seq.product * z

The same applies to Set, Iterator

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
seq.reduce(_ min _)
seq.fold(z)(_ min _)
// After
seq.min
z min seq.min
       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
seq.reduce(_ max _)
seq.fold(z)(_ max _)
// After
seq.max
z max seq.max

The same applies to Set, Iterator

Don't copy forall

       
       
       
1
2
3
4
5
6
       
       
       
// Before
seq.foldLeft( true)((x, y) => x && p(y))
!seq.map(p).contains( false)
// After
seq.forall(p)

The same applies to Set, Option (for the second line), Iterator

Don't copy exists

       
       
       
1
2
3
4
5
6
       
       
       
// Before
seq.foldLeft( false)((x, y) => x || p(y))
seq.map(p).contains( true)
// After
seq.exists(p)

Rewriting

Merge successive filter call

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.filter(p1).filter(p2)
// After
seq.filter(x => p1(x) && p2(x))

or seq.view.filter(p1).filter(p2).force

The same applies to Set, Option, Map, Iterator

Merge successive map call

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.map(f).map(g)
// After
seq.map(f.andThen(g))

or seq.view.map(f).map(g).force

The same applies to Set, Option, Map, Iterator

filter Sort after

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.sorted.filter(p)
// After
seq.filter(p).sorted

Calling map Do not explicitly call invert before reverse

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.reverse.map(f)
// After
seq.reverseMap(f)

Don't show the inverted iterator

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.reverse.iterator
// After
seq.reverseIterator

Do not convert a collection to Set Get an unrepeatable set

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.toSet.toSeq
// After
seq.distinct

Don't copy slice

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.drop(x).take(y)
// After
seq.slice(x, x + y)

The same applies to Set, Map, Iterator

Don't copy splitAt

       
       
       
1
2
3
4
5
6
       
       
       
// Before
val seq1 = seq.take(n)
val seq2 = seq.drop(n)
// After
val (seq1, seq2) = seq.spiltAt(n)

Don't copy span

       
       
       
1
2
3
4
5
6
       
       
       
// Before
val seq1 = seq.takeWhile(p)
val seq2 = seq.dropWhile(p)
// After
val (seq1, seq2) = seq.span(p)

Don't copy partition

       
       
       
1
2
3
4
5
6
       
       
       
// Before
val seq1 = seq.filter(p)
val seq2 = seq.filterNot(p)
// After
val (seq1, seq2) = seq.partition(p)

Don't copy takeRight

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.reverse.take(n).reverse
// After
seq.takeRight(n)

Don't copy flatten

       
       
       
1
2
3
4
5
6
       
       
       
// Before (seq: Seq[Seq[T]])
seq.flatMap(it => it)
seq.flatMap(identity)
// After
seq.flatten

The same applies to Set, Map, Iterator

Don't copy flatMap

       
       
       
1
2
3
4
5
       
       
       
// Before (f: A => Seq[B])
seq.map(f).flatten
// After
seq.flatMap(f)

The same applies to Set, Option, Iterator

Don't use... When you don't need results map

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.map(...) // the result is ignored
// After
seq.foreach(...)

The same applies to Set, Option, Map, Iterator

Do not generate temporary collections

1. Use view

       
       
       
1
2
3
4
5
       
       
       
// Before
seq.map(f).flatMap(g).filter(p).reduce(...)
// After
seq.view.map(f).flatMap(g).filter(p).reduce(...)
  1. take view Convert to a collection of the same type
       
       
       
1
2
3
4
5
       
       
       
// Before
seq.map(f).flatMap(g).filter(p)
// After
seq.view.map(f).flatMap(g).filter(p).force

If the intermediate conversion is filter, just so so

       
       
       
1
       
       
       
seq.withFilter( p). map( f)
  1. take view Convert to another set
       
       
       
1
2
3
4
5
       
       
       
// Before
seq.map(f).flatMap(g).filter(p).toList
// After
seq.view.map(f).flatMap(g).filter(p).toList

There is another kind. “transformation + conversion” Method :

       
       
       
1
       
       
       
seq.map(f)(collection.breakOut): List[T]

Use the assignment operator

       
       
       
1
2
3
4
5
6
7
8
9
10
11
       
       
       
// Before
seq = seq :+ x
seq = x +: seq
seq1 = seq1 ++ seq2
seq1 = seq2 ++ seq1
// After
seq :+= x
seq +:= x
seq1 ++= seq2
seq1 ++:= seq2

Scala There is a grammar sugar , Automatically put x <op>= y convert to x = x <op> y. If op With : ending , Is considered to be a right associative operator .
some list and stream The grammar of :

       
       
       
1
2
3
4
5
6
7
8
9
10
11
12
13
       
       
       
// Before
list = x :: list
list1 = list2 ::: list
stream = x #:: list
stream1 = stream2 #::: stream
// After
list ::= x
list1 :::= list2
stream #::= x
stream1 #:::= stream2

The same applies to Set, Map, Iterator

Set

Most of Seq This technique can also be applied to Set. Others are only for Set The technique of .

Do not use sameElements Compare unordered sets

       
       
       
1
2
3
4
5
       
       
       
// Before
set1.sameElements(set2)
// After
set1 == set2

The same applies to Map

Don't calculate the intersection manually

       
       
       
1
2
3
4
5
6
       
       
       
// Before
set1.filter(set2.contains)
set1.filter(set2)
// After
set1.intersect(set2) // or set1 & set2

Don't calculate by hand diff

       
       
       
1
2
3
4
5
6
       
       
       
// Before
set1.filterNot(set2.contains)
set1.filterNot(set2)
// After
set1.diff(set2) // or set1 &~ set2

Option

Option Not a collection class , But it provides similar methods and behavior .
Mostly for Seq This technique also applies to Option. Here are some special ones for Option The technique of .

Value

Do not use None and Option Compare

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
option == None
option != None
// After
option.isEmpty
option.isDefined

Do not use Some and Option Compare

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
option == Some(v)
option != Some(v)
// After
option.contains(v)
!option.contains(v)

Do not use instance types to check the existence of values

       
       
       
1
2
3
4
5
       
       
       
// Before
option.isInstanceOf[Some[_]]
// After
option.isDefined

Do not use pattern matching to check the existence of values

       
       
       
1
2
3
4
5
6
7
8
       
       
       
// Before
option match {
case Some(_) => true
case None => false
}
// After
option.isDefined

The same applies Seq, Set

Don't negate the existence checking property

       
       
       
1
2
3
4
5
6
7
8
9
       
       
       
// Before
!option.isEmpty
!option.isDefined
!option.nonEmpty
// After
seq.isDefined
seq.isEmpty
seq.isEmpty

Do not check the existence of the value and then process the value

       
       
       
1
2
3
4
5
6
7
8
9
10
       
       
       
// Before
if (option.isDefined) {
val v = option.get
...
}
// After
option.foreach { v =>
...
}

Null

Don't pass and null Compare to construct Option

       
       
       
1
2
3
4
5
       
       
       
// Before
if (v != null) Some(v) else None
// After
Option(v)

Do not display the provided null As an alternative

       
       
       
1
2
3
4
5
       
       
       
// Before
option.getOrElse( null)
// After
option.orNull

Rewriting

take map with getOrElse convert to fold

       
       
       
1
2
3
4
5
       
       
       
// Before
option.map(f).getOrElse(z)
// After
option.fold(z)(f)

Don't copy exists

       
       
       
1
2
3
4
5
       
       
       
// Before
option.map(p).getOrElse( false)
// After
option.exists(p)

Don't put... By hand option convert to sequence

       
       
       
1
2
3
4
5
6
       
       
       
// Before
option.map(Seq(_)).getOrElse(Seq.empty)
option.getOrElse(Seq.empty) // option: Option[Seq[T]]
// After
option.toSeq

Map

ditto , Only for map The technique of

Do not use lift Replace get

       
       
       
1
2
3
4
5
       
       
       
// Before
map.lift(n)
// After
map.get(n)

Because there is no special need to map The value is converted to a Option.

Do not call... Separately get and getOrElse

       
       
       
1
2
3
4
5
       
       
       
// Before
map.get(k).getOrElse(z)
// After
map.getOrElse(k, z)

Do not manually extract key sets

       
       
       
1
2
3
4
5
6
7
8
9
       
       
       
// Before
map.map(_._1)
map.map(_._1).toSet
map.map(_._1).toIterator
// After
map.keys
map.keySet
map.keysIterator

Do not manually extract value sets

       
       
       
1
2
3
4
5
6
7
       
       
       
// Before
map.map(_._2)
map.map(_._2).toIterator
// After
map.values
map.valuesIterator

Careful use filterKeys

       
       
       
1
2
3
4
5
       
       
       
// Before
map.filterKeys(p)
// After
map.filter(p(_._1))

because filterKeys Wrapped the original collection , No copied elements , Follow up treatment should be careful .

Careful use mapValues

       
       
       
1
2
3
4
5
       
       
       
// Before
map.mapValues(f)
// After
map.map(f(_._2))

ditto .

Don't do it by hand filter key

       
       
       
1
2
3
4
5
       
       
       
// Before
map.filterKeys(!seq.contains(_))
// After
map -- seq

Use the assignment operator to reassign

       
       
       
1
2
3
4
5
6
7
8
9
10
11
       
       
       
// Before
map = map + x -> y
map1 = map1 ++ map2
map = map - x
map = map -- seq
// After
map += x -> y
map1 ++= map2
map -= x
map --= seq

Add

In addition to the above introduction , I suggest you look at the official documents Scala Collections documentation.

also

The last paragraph is the author's modest words , Comments and suggestions are welcome .

版权声明
本文为[Bird's nest]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/10/20211009000611613w.html