内容简介:We keep working on Kotlin 1.4 and the next previewHere are some key improvements in the standard library in 1.4-M2:Even though Kotlin 1.4-M2 hasn’t been released yet, we’ve deployed its early version to the
We keep working on Kotlin 1.4 and the next preview 1.4-M2 is just around the corner. Right now we’re ready to unveil some improvements from this preview; in this post, we’ll get you acquainted with the standard library changes.
Here are some key improvements in the standard library in 1.4-M2:
- Changes to the existing API like updating signatures and introducing new constants
- More functions in thecommon library
- New functions forArrays andCollections
- Property delegation improvements
Even though Kotlin 1.4-M2 hasn’t been released yet, we’ve deployed its early version to the Kotlin playground so that you can try everything you find in this post. The code samples in this post run on the new version as well.
If you can’t wait to try the new version, subscribe to the Kotlin blog newsletter and you won’t miss the release day.
Extending the common library
You can use the standard library in “common” code – the code shared between different platforms, be they Android & iOS or JVM & JS. We’re gradually extending the common library and adding or moving missing functionality to it.
The previous implementation of appendln
in Kotlin/JVM added a system-dependent line separator ( \n
on UNIX systems and \r\n
on Windows). However, we feel it is important to guarantee the same behavior independently of the operating system, and independently of the underlying platform if we’re talking about common code. This is why we’re deprecating appendln
in favor of the new appendLine
function, which always terminates lines with a single \n
character:
fun main() { //sampleStart println(buildString { appendLine("Hello,") appendLine("Kotlin 1.4-M2") }) //sampleEnd }
You can still use System.lineSeparator()
in the JVM when you need a platform-specific separator.
The other functions that can now be used in common code allow you to use the string representation of the given stack trace. The Throwable.stackTraceToString()
extension returns the detailed description of this throwable with its stack trace, and Throwable.printStackTrace()
prints this description to the standard error output.
In common code, you can also use the Throwable.addSuppressed()
function, which allows you to specify the exceptions that were suppressed in order to deliver the exception, and the Throwable.suppressedExceptions
property, which returns a list of all the suppressed exceptions.
New array functions
To provide a consistent experience when working with different container types, we’ve added new extension functions for arrays:
shuffle() onEach()
These functions should be familiar to those who use lists; they work for arrays the same way.
fun main() { //sampleStart var language = "" val letters = arrayOf("k", "o", "t", "l", "i", "n") val fileExt = letters.onEach { language += it } .filterNot { it in "aeuio" }.take(2) .joinToString(prefix = ".", separator = "") println(language) // "kotlin" println(fileExt) // ".kt" letters.shuffle() println(letters.contentToString()) //sampleEnd }
We’ve also added new functions for sorting array subranges. Previously, there was
sort()
with parameters fromIndex
and toIndex
, which was JVM-only. Now it is common, and so are two new related functions, which are subrange versions of reverse()
and sortDescending()
. Each of these takes two indices and reorders the elements between them (including fromIndex
but excluding toIndex
) in ways that are hopefully evident from their names:
reverse() sortDescending()
fun main() { //sampleStart val letters = arrayOf("i", "o", "k", "l", "t", "n") letters.reverse(0, 3) letters.sortDescending(2, 5) println(letters.contentToString()) // [k, o, t, l, i, n] //sampleEnd }
New functions in collections API
In 1.4-M2, we continue expanding the collections API in the standard library to cover more real-life cases:
-
A new set creation function
setOfNotNull()
makes a set consisting of all the non-null items among the provided arguments.
fun main() { //sampleStart val set = setOfNotNull(null, 1, 2, 0, null) println(set) //sampleEnd }
-
shuffled()
is now available for sequences.
fun main() { //sampleStart val numbers = (0 until 50).asSequence() val result = numbers.map { it * 2 }.shuffled().take(5) println(result.toList()) //five random even numbers below 100 //sampleEnd }
-
onEachIndexed()
andreduceIndexedOrNull()
have been added as counterparts for onEach() and reduceOrNull() , respectively. As you may already know,Indexed
in the name of a collection-processing function means that the operation applied has the element index as a parameter.
fun main() { //sampleStart val list = mutableListOf("a", "b", "c", "d").onEachIndexed { index, item -> println(index.toString() + ":" + item) } val emptyList = emptyList<Int>() emptyList.reduceIndexedOrNull {index, a, b -> index + a + b} // null //sampleEnd }
-
runningFold()
andrunningReduce()
are introduced as synonyms forscan()
andscanReduce()
. Such names are more consistent with the related functionsfold()
andreduce()
. In the future,scan()
will be available along withrunningFold()
since it’s a commonly known name for this operation. The experimentalscanReduce()
, however, will be deprecated and removed soon.
fun main() { //sampleStart val numbers = mutableListOf(0, 1, 2, 3, 4, 5) val runningReduceSum = numbers.runningReduce() { sum, item -> sum + item} // [0, 1, 3, 6, 10, 15] val runningFoldSum = numbers.runningFold(10) { sum, item -> sum + item} // [10, 10, 11, 13, 16, 20, 25] //sampleEnd }
Improving the existing API
As Kotlin 1.4 is a major “feature” release, we can add new features to the language, and new functions or interfaces to the standard library. We only add new experimental declarations in incremental releases (like 1.3.70). If you’re writing code using Kotlin 1.3.70 and you don’t use any experimental declarations, your code will compile just fine for your teammates who use Kotlin 1.3.40.
Feature releases don’t need to obey the same strict rules as minor ones, meaning that if you use a new feature or API, the Kotlin compiler of the 1.3 version may not compile code written in Kotlin 1.4. This allows us to introduce some changes to the API in order to improve it. We do try to carefully observe backward compatibility so that your code written for the older version continues to compile and work as before.
In Kotlin 1.4, we’ve relaxed several functions to accept null
s:
fun main() { //sampleStart val s: String? = null println(s.toBoolean()) // false //sampleEnd }
Kotlin 1.3 won’t compile this code because it requires the receiver of String.toBoolean()
to be non-nullable. Kotlin 1.4 changes the receiver to a nullable string: String?.toBoolean()
. Still, all the code you’ve written before continues to compile and work in Kotlin 1.4.
The same logic applies to the Array
receiver of the contentEquals
, contentHashCode
, and contentToString
functions: now it’s nullable. Also, String.format()
now allows null
as a locale
argument, in which case no localization is applied.
The following constants defined in Double
s and Float
s are now “real” constants:
fun main() { //sampleStart println(Double.NaN) // NaN println(Double.NEGATIVE_INFINITY) // -Infinity println(Double.POSITIVE_INFINITY > Double.MAX_VALUE ) // true println(Double.SIZE_BITS) // 64 //sampleEnd }
They are now defined as const
variables, so you can use them as annotation arguments.
SIZE_BITS
and SIZE_BYTES
are new constants in Double
and Float
; they contain the number of bits and bytes accordingly used to represent an instance of the type in binary form.
Note that we’ve also changed the Float.MAX_VALUE
and Float.MIN_VALUE
values in Kotlin/JS. Before, they were equal to JavaScript Number.MAX/MIN_VALUE
, or equivalently, Double.MAX/MIN_VALUE
, because Float
is essentially equivalent to Double
in Kotlin/JS. Now, these Float
range constants are the same for all platforms.
maxOf() and minOf() with varargs
The maxOf()
and minOf()
functions from the standard library find the greater and the smaller of two values. Starting with 1.4-M1, maxOf()
and minOf()
can accept a variable number of arguments
( vararg
), allowing you to use them on any sets of numbers or other comparable items.
fun main() { //sampleStart val max = maxOf(1, 2, 3, 4) println(max) //sampleEnd }
Property delegation improvements
In Kotlin, delegated properties work via conventions, not interfaces: the type you want to use as a delegate must define an operator function rather than implement the required interface. This provides flexibility (as we aren’t bound by specific interfaces), but in many practical use cases, it still is helpful to use interfaces.
In Kotlin 1.4, we’ve made such complementary interfaces even better to work with: we’ve introduced a new PropertyDelegateProvider
interface, and ReadWriteProperty
now inherits ReadOnlyProperty
. Please read on for more details.
Delegate expression
The ReadWriteProperty
and ReadOnlyProperty
interfaces are handy for defining property delegates as your custom class or anonymous object can implement them:
fun myDelegate(): ReadWriteProperty<Nothing?, Int> = object : ReadWriteProperty<Nothing?, Int> { ... } val foo: Int by myDelegate() var bar: Int by myDelegate()
Starting with 1.4, ReadWriteProperty
inherits ReadOnlyProperty
. This gives you more flexibility for working with delegate expressions. In our example, now you can pass the myDelegate()
call whenever a ReadOnlyProperty
is expected.
Here we’d like to emphasize that “read-only” isn’t the same as “immutable” in Kotlin, similarly to how a read-only list is not an immutable list. “Read-only” means “this interface provides only read-only access to the object in question”.
Providing a delegate
By using the mechanism of providing a delegate, you can extend the logic of creating a “delegate” object – the object to which the property implementation is delegated. You can find the details of how it works in the documentation
. In 1.4, to make this mechanism a bit more convenient, we’ve added a new PropertyDelegateProvider
interface. You can use it when you don’t want to create an extra class and prefer using an anonymous object, similar to what we’ve seen in myDelegate()
example above.
Delegating to another property
Starting with 1.4, a property can delegate its getter and setter directly to another property. This may be useful, for instance, when you want to rename a property in a backward-compatible way: you introduce a new property, annotate an old one with the @Deprecated
annotation, and delegate its implementation.
class MyClass { var newName: Int = 0 @Deprecated("Use 'newName' instead", ReplaceWith("newName")) var oldName: Int by this::newName } fun main() { val myClass = MyClass() // Notification: 'oldName: Int' is deprecated. // Use 'newName' instead myClass.oldName = 42 println(myClass.newName) // 42 }
The optimization for compiled delegated properties describedbefore works for this case. Since the delegation operator implementation doesn’t use the information about the property being delegated ( oldName
), there’s no need for the compiler to generate the KProperty
instance with that information. In the future, it will also be possible not to generate an additional KMutableProperty
instance for the delegate ( newName
).
How to try
All the described changes will be part of the Kotlin 1.4-M2 preview, but you can already try them online at play.kotl.in ; just make sure to select the version 1.4-M2 in the settings.
Pre-release notes
Note that backward compatibility guarantees do not cover pre-release versions. The features and API can change in subsequent releases based on your feedback.
Share your feedback
We’re thankful for all your bug reports in ourissue tracker. We’ll do our best to fix all the important issues before the final release so you won’t have to wait until yet another Kotlin release for them to be addressed.
You are also welcome to join the #eap channel in our Kotlin Slack (get an invite here ) to ask questions, participate in discussions, and get notifications of new preview builds.
Let’s Kotlin!
以上所述就是小编给大家介绍的《First Look at Kotlin 1.4-M2: Standard Library Improvements》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Data Mining
Bing Liu / Springer / 2011-6-26 / CAD 61.50
Web mining aims to discover useful information and knowledge from Web hyperlinks, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is not purely an ......一起来看看 《Web Data Mining》 这本书的介绍吧!