scala.collection.breakOut vs views

后端 未结 4 903
北海茫月
北海茫月 2021-02-19 08:01

This SO answer describes how scala.collection.breakOut can be used to prevent creating wasteful intermediate collections. For example, here we create an intermediat

相关标签:
4条回答
  • 2021-02-19 08:27

    What flavian said.

    One use case for views is to conserve memory. For example, if you had a million-character-long string original, and needed to use, one by one, all of the million suffixes of that string, you might use a collection of

    val v = original.view
    val suffixes = v.tails
    

    views on the original string. Then you might loop over the suffixes one by one, using suffix.force() to convert them back to strings within the loop, thus only holding one in memory at a time. Of course, you could do the same thing by iterating with your own loop over the indices of the original string, rather than creating any kind of collection of the suffixes.

    Another use-case is when creation of the derived objects is expensive, you need them in a collection (say, as values in a map), but you only will access a few, and you don't know which ones.

    If you really have a case where picking between them makes sense, prefer breakOut unless there's a good argument for using view (like those above).

    • Views require more code changes and care than breakOut, in that you need to add force() where needed. Depending on context, failure to do so is often only detected at run-time. With breakOut, generally if it compiles, it's right.
    • In cases where view does not apply, breakOut will be faster, since view generation and forcing is skipped.
    • If you use a debugger, you can inspect the collection contents, which you can't meaningfully do with a collection of views.
    0 讨论(0)
  • 2021-02-19 08:29

    I don't think views and breakOut are identical.

    A breakOut is a CanBuildFrom implementation used to simplify transformation operations by eliminating intermediary steps. E.g get from A to B without the intermediary collection. A breakOut means letting Scala choose the appropriate builder object for maximum efficiency of producing new items in a given scenario. More details here.

    views deal with a different type of efficiency, the main sale pitch being: "No more new objects". Views store light references to objects to tackle different usage scenarios: lazy access etc.

    Bottom line:

    If you map on a view you may still get an intermediary collection of references created before the expected result can be produced. You could still have superior performance from:

    collection.view.map(somefn)(breakOut)
    

    Than from:

    collection.view.map(someFn)
    
    0 讨论(0)
  • 2021-02-19 08:31

    As of Scala 2.13, this is no longer a concern. Breakout has been removed and views are the recommended replacement.


    Scala 2.13 Collections Rework

    Views are also the recommended replacement for collection.breakOut. For example,

    val s: Seq[Int] = ... 
    val set: Set[String] = s.map(_.toString)(collection.breakOut)
    

    can be expressed with the same performance characteristics as:

    val s: Seq[Int] = ... 
    val set = s.view.map(_.toString).to(Set)
    
    0 讨论(0)
  • 2021-02-19 08:40

    You're going to make a trip from England to France.

    With view: you're taking a set of notes in your notebook and boom, once you've called .force() you start making all of them: buy a ticket, board on the plane, ....

    With breakOut: you're departing and boom, you in the Paris looking at the Eiffel tower. You don't remember how exactly you've arrived there, but you did this trip actually, just didn't make any memories.

    Bad analogy, but I hope this give you a taste of what is the difference between them.

    0 讨论(0)
提交回复
热议问题