├── .gitignore ├── README.md ├── kotlinx-support-jdk7 ├── pom.xml └── src │ ├── main │ └── kotlin │ │ ├── AutoCloseable.kt │ │ └── Exceptions.kt │ └── test │ └── kotlin │ └── TryWithResourcesTest.kt ├── kotlinx-support-jdk8 ├── pom.xml └── src │ ├── main │ └── kotlin │ │ ├── collections │ │ ├── Collections.kt │ │ └── Streams.kt │ │ └── text │ │ └── CharSequences.kt │ └── test │ └── kotlin │ ├── collections │ ├── CollectionTest.kt │ ├── IterableTest.kt │ ├── ListTest.kt │ ├── MapTest.kt │ └── StreamsTest.kt │ └── text │ └── CharSequenceTest.kt └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | *.iml 3 | target -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kotlinx.support 2 | Provides extension and top-level functions to use JDK7/JDK8 features in Kotlin 1.0. 3 | 4 | In Kotlin 1.1+ please use the standard library artifacts instead: [`kotlin-stdlib-jdk7`](https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib-jdk7) and [`kotlin-stdlib-jdk8`](https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib-jdk8). 5 | 6 | [![obsolete JetBrains project](http://jb.gg/badges/obsolete.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [ ![Download](https://api.bintray.com/packages/kotlin/kotlinx.support/kotlinx.support/images/download.svg) ](https://bintray.com/kotlin/kotlinx.support/kotlinx.support/_latestVersion) 7 | 8 | ## Maven 9 | 10 | Add jcenter repository (if you don't have it yet) 11 | 12 | ```xml 13 | 14 | 15 | false 16 | 17 | central 18 | bintray 19 | https://jcenter.bintray.com 20 | 21 | ``` 22 | 23 | Add a dependency: 24 | 25 | ```xml 26 | 27 | org.jetbrains.kotlinx 28 | kotlinx-support-jdk8 29 | 0.3 30 | 31 | ``` 32 | 33 | ## Gradle 34 | 35 | Just add a dependency: 36 | 37 | ```groovy 38 | compile 'org.jetbrains.kotlinx:kotlinx-support-jdk8:0.3' 39 | ``` 40 | 41 | jcenter repository should be configured by default in gradle, but if it's not you may need to include it: 42 | 43 | ```groovy 44 | repositories { 45 | jcenter() 46 | } 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /kotlinx-support-jdk7/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.jetbrains.kotlinx 8 | kotlinx-support 9 | 0.1-SNAPSHOT 10 | 11 | 12 | kotlinx-support-jdk7 13 | jar 14 | 15 | Kotlin JDK7 support library 16 | 17 | 18 | src/main/kotlin 19 | src/test/kotlin 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /kotlinx-support-jdk7/src/main/kotlin/AutoCloseable.kt: -------------------------------------------------------------------------------- 1 | package kotlinx.support.jdk7 2 | 3 | /** 4 | * Executes the given [block] function on this resource and then closes it down correctly whether an exception 5 | * is thrown or not. 6 | * 7 | * In case if the resource is being closed due to an exception occurred in [block], and the closing also fails with an exception, 8 | * the latter is added to the [suppressed][java.lang.Throwable.addSuppressed] exceptions of the former. 9 | * 10 | * @param block a function to process this [AutoCloseable] resource. 11 | * @return the result of [block] function invoked on this resource. 12 | */ 13 | public inline fun T.use(block: (T) -> R): R { 14 | var closed = false 15 | try { 16 | return block(this) 17 | } catch (e: Throwable) { 18 | closed = true 19 | @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") 20 | this?.closeSuppressed(e) 21 | throw e 22 | } finally { 23 | if (this != null && !closed) { 24 | close() 25 | } 26 | } 27 | } 28 | 29 | /** 30 | * Closes this [AutoCloseable] suppressing possible exception or error thrown by [AutoCloseable.close] function. 31 | * The suppressed exception is added to the list of suppressed exceptions of [cause] exception. 32 | */ 33 | internal fun AutoCloseable.closeSuppressed(cause: Throwable) { 34 | try { 35 | close() 36 | } catch (closeException: Throwable) { 37 | cause.addSuppressed(closeException) 38 | } 39 | } 40 | 41 | /* 42 | // seems to have marginal use cases 43 | public fun AutoCloseable.closeQuietly(): Throwable? { 44 | return try { 45 | close() 46 | null 47 | } 48 | catch (e: Throwable) { 49 | e 50 | } 51 | } 52 | */ 53 | -------------------------------------------------------------------------------- /kotlinx-support-jdk7/src/main/kotlin/Exceptions.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "NOTHING_TO_INLINE") 2 | package kotlinx.support.jdk7 3 | 4 | /** 5 | * Appends the specified exception to the exceptions that were 6 | * suppressed in order to deliver this exception. 7 | */ 8 | public inline fun Throwable.addSuppressed(exception: Throwable) = (this as java.lang.Throwable).addSuppressed(exception) 9 | 10 | 11 | /** 12 | * Returns an array containing all of the exceptions that were suppressed. 13 | */ 14 | public inline fun Throwable.getSuppressed(): Array = (this as java.lang.Throwable).suppressed 15 | 16 | /** 17 | * Returns an array containing all of the exceptions that were suppressed. 18 | */ 19 | public val Throwable.suppressed: Array 20 | @JvmName("suppressed") 21 | get() = (this as java.lang.Throwable).suppressed 22 | -------------------------------------------------------------------------------- /kotlinx-support-jdk7/src/test/kotlin/TryWithResourcesTest.kt: -------------------------------------------------------------------------------- 1 | package kotlinx.support.jdk7.test 2 | 3 | import kotlinx.support.jdk7.getSuppressed 4 | import kotlinx.support.jdk7.suppressed 5 | import java.io.* 6 | import org.junit.Test 7 | import kotlin.test.* 8 | 9 | import kotlinx.support.jdk7.use 10 | import java.util.* 11 | 12 | @Suppress("HasPlatformType") fun platformNull() = Collections.singletonList(null as T).first() 13 | 14 | class Resource(val faultyClose: Boolean = false) : Closeable { 15 | 16 | var isClosed = false 17 | private set 18 | 19 | override fun close() { 20 | if (faultyClose) 21 | throw IOException("Close failed") 22 | isClosed = true 23 | } 24 | } 25 | 26 | class TryWithResourcesTest { 27 | @Test fun success() { 28 | val resource = Resource() 29 | val result = resource.use { "ok" } 30 | assertEquals("ok", result) 31 | assertTrue(resource.isClosed) 32 | } 33 | 34 | @Test fun closeFails() { 35 | val e = assertFails { 36 | Resource(faultyClose = true).use { "" } 37 | } 38 | assertTrue(e is IOException) 39 | } 40 | 41 | @Test fun opFailsCloseSuccess() { 42 | val e = assertFails { 43 | Resource().use { error("op fail") } 44 | } 45 | assertTrue(e is IllegalStateException) 46 | assertTrue(e.suppressed.isEmpty()) 47 | } 48 | 49 | @Test fun opFailsCloseFails() { 50 | val e = assertFails { 51 | Resource(faultyClose = true).use { error("op fail") } 52 | } 53 | assertTrue(e is IllegalStateException) 54 | assertTrue(e.suppressed.single() is IOException) 55 | } 56 | 57 | @Test fun opFailsCloseFailsTwice() { 58 | val e = assertFails { 59 | Resource(faultyClose = true).use { res1 -> 60 | Resource(faultyClose = true).use { res2 -> 61 | error("op fail") 62 | } 63 | } 64 | } 65 | assertTrue(e is IllegalStateException) 66 | val suppressed = e.getSuppressed() 67 | assertEquals(2, suppressed.size) 68 | assertTrue(suppressed.all { it is IOException }) 69 | } 70 | 71 | @Test fun nonLocalReturnInBlock() { 72 | fun Resource.operation(nonLocal: Boolean): String { 73 | return use { if (nonLocal) return "nonLocal" else "local" } 74 | } 75 | 76 | Resource().let { resource -> 77 | val result = resource.operation(nonLocal = false) 78 | assertEquals("local", result) 79 | assertTrue(resource.isClosed) 80 | } 81 | 82 | Resource().let { resource -> 83 | val result = resource.operation(nonLocal = true) 84 | assertEquals("nonLocal", result) 85 | assertTrue(resource.isClosed) 86 | } 87 | 88 | } 89 | 90 | @Test fun nullableResourceSuccess() { 91 | val resource: Resource? = null 92 | val result = resource.use { "ok" } 93 | assertEquals("ok", result) 94 | } 95 | 96 | @Test fun nullableResourceOpFails() { 97 | val resource: Resource? = null 98 | val e = assertFails { 99 | resource.use { requireNotNull(it) } 100 | } 101 | assertTrue(e is IllegalArgumentException) 102 | assertTrue(e.suppressed.isEmpty()) 103 | } 104 | 105 | @Test fun platformResourceOpFails() { 106 | val resource = platformNull() 107 | val e = assertFails { 108 | resource.use { requireNotNull(it) } 109 | } 110 | assertTrue(e is IllegalArgumentException) 111 | assertTrue(e.suppressed.isEmpty()) 112 | } 113 | 114 | 115 | } -------------------------------------------------------------------------------- /kotlinx-support-jdk8/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.jetbrains.kotlinx 8 | kotlinx-support 9 | 0.1-SNAPSHOT 10 | 11 | 12 | kotlinx-support-jdk8 13 | jar 14 | 15 | Kotlin JDK8 support library 16 | 17 | 18 | src/main/kotlin 19 | src/test/kotlin 20 | 21 | 22 | 23 | 24 | org.jetbrains.kotlinx 25 | kotlinx-support-jdk7 26 | ${version} 27 | compile 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /kotlinx-support-jdk8/src/main/kotlin/collections/Collections.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST", "NOTHING_TO_INLINE") 2 | package kotlinx.support.jdk8.collections 3 | 4 | import java.util.* 5 | import java.util.function.* 6 | import java.util.stream.Stream 7 | 8 | 9 | // forEach (Ljava/util/function/Consumer<-TT;>;)V 10 | 11 | /** 12 | * Performs the given action for each element of the [Iterable]. 13 | */ 14 | public inline fun Iterable.forEach(action: Consumer): Unit 15 | = (this as java.lang.Iterable).forEach(action) 16 | 17 | // do not provide overload with function as we have inline Iterable.forEach implementation. 18 | 19 | 20 | 21 | // spliterator ()Ljava/util/Spliterator; 22 | 23 | /** 24 | * Creates a [Spliterator] over the elements described by this [Iterable]. 25 | */ 26 | public inline fun Iterable.spliterator(): Spliterator 27 | = (this as java.lang.Iterable).spliterator() 28 | 29 | 30 | 31 | // forEachRemaining (Ljava/util/function/Consumer<-TE;>;)V 32 | 33 | /** 34 | * Performs the given action for each remaining element returned by this [Iterator]. 35 | */ 36 | public inline fun Iterator.forEachRemaining(action: Consumer): Unit 37 | = (this as java.util.Iterator).forEachRemaining(action) 38 | 39 | // do not provide overload with function as we may provide inline implementation, like Iterable.forEach 40 | 41 | ///** 42 | // * Performs the given action for each remaining element returned by this [Iterator]. 43 | // */ 44 | //public inline fun Iterator.forEachRemaining(crossinline action: (T) -> Unit): Unit 45 | // = (this as java.util.Iterator).forEachRemaining { action(it) } 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | // removeIf (Ljava/util/function/Predicate<-TE;>;)Z 55 | 56 | /** 57 | * Removes all of the elements of this collection that satisfy the given [filter] predicate. 58 | */ 59 | public inline fun MutableCollection.removeIf(filter: Predicate): Boolean 60 | = (this as java.util.Collection).removeIf(filter) 61 | 62 | /** 63 | * Removes all of the elements of this collection that satisfy the given [filter] predicate. 64 | */ 65 | public inline fun MutableCollection.removeIf(crossinline filter: (T) -> Boolean): Boolean 66 | = (this as java.util.Collection).removeIf { filter(it) } 67 | 68 | 69 | 70 | // stream ()Ljava/util/stream/Stream; 71 | /** 72 | * Returns a sequential [Stream] with this collection as its source. 73 | */ 74 | public inline fun Collection.stream(): Stream 75 | = (this as java.util.Collection).stream() 76 | 77 | 78 | 79 | // parallelStream ()Ljava/util/stream/Stream; 80 | /** 81 | * Returns a possibly parallel [Stream] with this collection as its source. 82 | */ 83 | public inline fun Collection.parallelStream(): Stream 84 | = (this as java.util.Collection).parallelStream() 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | // replaceAll (Ljava/util/function/UnaryOperator;)V 94 | 95 | /** 96 | * Replaces each element of this list with the result of applying the 97 | * [operator] to that element. 98 | */ 99 | public inline fun MutableList.replaceAll(operator: UnaryOperator): Unit 100 | = (this as java.util.List).replaceAll(operator) 101 | 102 | /** 103 | * Replaces each element of this list with the result of applying the 104 | * [operator] to that element. 105 | */ 106 | public inline fun MutableList.replaceAll(crossinline operator: (T) -> T): Unit 107 | = (this as java.util.List).replaceAll { operator(it) } 108 | 109 | 110 | 111 | // sort (Ljava/util/Comparator<-TE;>;)V 112 | // ? 113 | // public inline fun MutableList.sort(comparator: Comparator) = (this as java.util.List).sort(comparator) 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | // getOrDefault (Ljava/lang/Object;TV;)TV; 122 | 123 | /** 124 | * Returns the value to which the specified key is mapped, or 125 | * [defaultValue] if this map contains no mapping for the key. 126 | */ 127 | @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") 128 | public inline fun <@kotlin.internal.OnlyInputTypes K, V> Map.getOrDefault(key: K, defaultValue: V): V 129 | = (this as java.util.Map).getOrDefault(key, defaultValue) 130 | 131 | 132 | 133 | // forEach (Ljava/util/function/BiConsumer<-TK;-TV;>;)V 134 | /** 135 | * Performs the given [action] for each entry in this map. 136 | */ 137 | public inline fun Map.forEach(action: BiConsumer): Unit 138 | = (this as java.util.Map).forEach(action) 139 | 140 | // ? 141 | /** 142 | * Performs the given [action] for each entry in this map. 143 | */ 144 | public inline fun Map.forEach(crossinline action: (K, V) -> Unit): Unit 145 | = (this as java.util.Map).forEach { k, v -> action(k, v)} 146 | 147 | 148 | 149 | // replaceAll (Ljava/util/function/BiFunction<-TK;-TV;+TV;>;)V 150 | 151 | /** 152 | * Replaces each entry's value with the result of invoking the given 153 | * [function] on that entry. 154 | */ 155 | public inline fun MutableMap.replaceAll(function: BiFunction): Unit 156 | = (this as java.util.Map).replaceAll(function) 157 | 158 | /** 159 | * Replaces each entry's value with the result of invoking the given 160 | * [function] on that entry. 161 | */ 162 | public inline fun MutableMap.replaceAll(crossinline function: (K, V) -> V): Unit 163 | = (this as java.util.Map).replaceAll { k, v -> function(k, v) } 164 | 165 | 166 | 167 | // putIfAbsent (TK;TV;)TV; 168 | 169 | /** 170 | * If the specified key is not already associated with a value (or is mapped 171 | * to `null`) associates it with the given value and returns 172 | * `null`, else returns the current value. 173 | */ 174 | public inline fun MutableMap.putIfAbsent(key: K, value: V): V? 175 | = (this as java.util.Map).putIfAbsent(key, value) 176 | 177 | 178 | 179 | // remove (Ljava/lang/Object;Ljava/lang/Object;)Z 180 | 181 | /** 182 | * Removes the entry for the specified key only if it is currently 183 | * mapped to the specified value. 184 | */ 185 | @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") 186 | public inline fun <@kotlin.internal.OnlyInputTypes K, @kotlin.internal.OnlyInputTypes V> MutableMap.remove(key: K, value: V): Boolean 187 | = (this as java.util.Map).remove(key, value) 188 | 189 | 190 | 191 | // replace (TK;TV;TV;)Z 192 | // ? out K 193 | 194 | /** 195 | * Replaces the entry for the specified key only if currently 196 | * mapped to the specified value. 197 | */ 198 | public inline fun MutableMap.replace(key: K, oldValue: V, newValue: V): Boolean 199 | = (this as java.util.Map).replace(key, oldValue, newValue) 200 | 201 | 202 | 203 | // replace (TK;TV;)TV; 204 | 205 | /** 206 | * Replaces the entry for the specified key only if it is 207 | * currently mapped to some value. 208 | */ 209 | public inline fun MutableMap.replace(key: K, value: V): V? 210 | = (this as java.util.Map).replace(key, value) 211 | 212 | 213 | 214 | // computeIfAbsent (TK;Ljava/util/function/Function<-TK;+TV;>;)TV; 215 | 216 | /** 217 | * If the specified key is not already associated with a value (or is mapped 218 | * to `null`), attempts to compute its value using the given mapping 219 | * function and enters it into this map unless `null`. 220 | */ 221 | public inline fun MutableMap.computeIfAbsent(key: K, mappingFunction: java.util.function.Function): V? 222 | = (this as java.util.Map).computeIfAbsent(key, mappingFunction) 223 | 224 | /** 225 | * If the specified key is not already associated with a value (or is mapped 226 | * to `null`), attempts to compute its value using the given mapping 227 | * function and enters it into this map unless `null`. 228 | */ 229 | public inline fun MutableMap.computeIfAbsent(key: K, crossinline mappingFunction: (K) -> V?): V? 230 | = (this as java.util.Map).computeIfAbsent(key, java.util.function.Function { mappingFunction(it) }) 231 | 232 | 233 | 234 | // computeIfPresent (TK;Ljava/util/function/BiFunction<-TK;-TV;+TV;>;)TV; 235 | /** 236 | * If the value for the specified key is present and non-null, attempts to 237 | * compute a new mapping given the key and its current mapped value. 238 | */ 239 | public inline fun MutableMap.computeIfPresent(key: K, remappingFunction: BiFunction): V? 240 | = (this as java.util.Map).computeIfPresent(key, remappingFunction) 241 | 242 | /** 243 | * If the value for the specified key is present and non-null, attempts to 244 | * compute a new mapping given the key and its current mapped value. 245 | */ 246 | public inline fun MutableMap.computeIfPresent(key: K, crossinline remappingFunction: (K, V) -> V?): V? 247 | = (this as java.util.Map).computeIfPresent(key, BiFunction { k, v -> remappingFunction(k, v)}) 248 | 249 | 250 | 251 | // compute (TK;Ljava/util/function/BiFunction<-TK;-TV;+TV;>;)TV; 252 | /** 253 | * Attempts to compute a mapping for the specified key and its current 254 | * mapped value (or `null` if there is no current mapping). 255 | */ 256 | public inline fun MutableMap.compute(key: K, remappingFunction: BiFunction): V? 257 | = (this as java.util.Map).compute(key, remappingFunction) 258 | 259 | /** 260 | * Attempts to compute a mapping for the specified key and its current 261 | * mapped value (or `null` if there is no current mapping). 262 | */ 263 | public inline fun MutableMap.compute(key: K, crossinline remappingFunction: (K, V?) -> V?): V? 264 | = (this as java.util.Map).compute(key, BiFunction { k, v -> remappingFunction(k, v) }) 265 | 266 | 267 | // merge (TK;TV;Ljava/util/function/BiFunction<-TV;-TV;+TV;>;)TV; 268 | // ? value parameter and oldValue, newValue in remappingFunction must be V!! (non-null subtype of any V) 269 | /** 270 | * If the specified key is not already associated with a value or is 271 | * associated with `null`, associates it with the given non-null value. 272 | * Otherwise, replaces the associated value with the results of the given 273 | * remapping function, or removes if the result is `null`. This 274 | * method may be of use when combining multiple mapped values for a key. 275 | */ 276 | public inline fun MutableMap.merge(key: K, value: V, remappingFunction: BiFunction): V? 277 | = (this as java.util.Map).merge(key, value, remappingFunction) 278 | 279 | /** 280 | * If the specified key is not already associated with a value or is 281 | * associated with `null`, associates it with the given non-null value. 282 | * Otherwise, replaces the associated value with the results of the given 283 | * remapping function, or removes if the result is `null`. This 284 | * method may be of use when combining multiple mapped values for a key. 285 | */ 286 | public inline fun MutableMap.merge(key: K, value: V, crossinline remappingFunction: (V, V) -> V?): V? 287 | = (this as java.util.Map).merge(key, value, BiFunction { oldValue, newValue -> remappingFunction(oldValue, newValue) }) 288 | 289 | 290 | 291 | -------------------------------------------------------------------------------- /kotlinx-support-jdk8/src/main/kotlin/collections/Streams.kt: -------------------------------------------------------------------------------- 1 | package kotlinx.support.jdk8.streams 2 | 3 | import java.util.* 4 | import java.util.stream.* 5 | 6 | /** 7 | * Creates a [Sequence] instance that wraps the original stream iterating through its elements. 8 | */ 9 | public fun Stream.asSequence(): Sequence = Sequence { iterator() } 10 | 11 | /** 12 | * Creates a [Sequence] instance that wraps the original stream iterating through its elements. 13 | */ 14 | public fun IntStream.asSequence(): Sequence = Sequence { iterator() } 15 | 16 | /** 17 | * Creates a [Sequence] instance that wraps the original stream iterating through its elements. 18 | */ 19 | public fun LongStream.asSequence(): Sequence = Sequence { iterator() } 20 | 21 | /** 22 | * Creates a [Sequence] instance that wraps the original stream iterating through its elements. 23 | */ 24 | public fun DoubleStream.asSequence(): Sequence = Sequence { iterator() } 25 | 26 | /** 27 | * Creates a sequential [Stream] instance that produces elements from the original sequence. 28 | */ 29 | public fun Sequence.asStream(): Stream = StreamSupport.stream({ Spliterators.spliteratorUnknownSize(iterator(), 0) }, 0, false) 30 | 31 | /** 32 | * Returns a [List] containing all elements produced by this stream. 33 | */ 34 | public fun Stream.toList(): List = collect(Collectors.toList()) 35 | 36 | /** 37 | * Returns a [List] containing all elements produced by this stream. 38 | */ 39 | public fun IntStream.toList(): List = toArray().asList() 40 | 41 | /** 42 | * Returns a [List] containing all elements produced by this stream. 43 | */ 44 | public fun LongStream.toList(): List = toArray().asList() 45 | 46 | /** 47 | * Returns a [List] containing all elements produced by this stream. 48 | */ 49 | public fun DoubleStream.toList(): List = toArray().asList() 50 | 51 | -------------------------------------------------------------------------------- /kotlinx-support-jdk8/src/main/kotlin/text/CharSequences.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "NOTHING_TO_INLINE") 2 | package kotlinx.support.jdk8.text 3 | 4 | import java.util.stream.IntStream 5 | 6 | /** 7 | * Returns an [IntStream] of UTF-16 character code values from this sequence. 8 | * Surrogate pairs are represented as pair of consecutive chars. 9 | */ 10 | inline fun CharSequence.chars(): IntStream = (this as java.lang.CharSequence).chars() 11 | 12 | /** 13 | * Returns an [IntStream] of UTF code point values from this sequence. 14 | */ 15 | inline fun CharSequence.codePoints(): IntStream = (this as java.lang.CharSequence).codePoints() -------------------------------------------------------------------------------- /kotlinx-support-jdk8/src/test/kotlin/collections/CollectionTest.kt: -------------------------------------------------------------------------------- 1 | package kotlinx.support.jdk8.collections.test 2 | 3 | import kotlinx.support.jdk8.collections.* 4 | import kotlinx.support.jdk8.streams.* 5 | import kotlinx.support.jdk8.text.* 6 | import org.junit.Test 7 | import kotlin.test.* 8 | import java.util.function.Predicate 9 | import java.util.stream.Collectors 10 | 11 | class CollectionTest { 12 | 13 | val data = listOf("abc", "fo", "baar") 14 | 15 | @Test fun stream() { 16 | assertEquals( 17 | data.flatMap { it.asIterable() }, 18 | data.stream() 19 | .flatMap { it.chars().boxed().map { it.toChar() } } 20 | .collect(Collectors.toList())) 21 | 22 | assertEquals(data, data.parallelStream().toList()) 23 | } 24 | 25 | 26 | @Test fun removeIf() { 27 | val coll: MutableCollection = data.toMutableList() 28 | assertTrue(coll.removeIf { it.length < 3 }) 29 | assertEquals(listOf("abc", "baar"), coll as Collection) 30 | assertFalse(coll.removeIf(Predicate { it.length > 4 })) 31 | } 32 | 33 | 34 | } -------------------------------------------------------------------------------- /kotlinx-support-jdk8/src/test/kotlin/collections/IterableTest.kt: -------------------------------------------------------------------------------- 1 | package kotlinx.support.jdk8.collections.test 2 | 3 | import kotlinx.support.jdk8.collections.* 4 | import org.junit.Test 5 | import kotlin.test.* 6 | import java.util.function.* 7 | 8 | 9 | 10 | class IterableTest { 11 | 12 | val data = listOf("foo", "bar") 13 | val iterable = Iterable { data.iterator() } 14 | 15 | @Test fun spliterator() { 16 | val spliterator = iterable.spliterator() 17 | 18 | assertEquals(-1, spliterator.exactSizeIfKnown) 19 | val expected = data.toMutableList() 20 | spliterator.forEachRemaining { 21 | assertEquals(expected.removeAt(0), it) 22 | } 23 | } 24 | 25 | @Test fun forEach() { 26 | val expected = data.toMutableList() 27 | iterable.forEach(Consumer { 28 | assertEquals(expected.removeAt(0), it) 29 | }) 30 | } 31 | 32 | @Test fun forEachRemaining() { 33 | val expected = data.toMutableList() 34 | val iterator = iterable.iterator() 35 | iterator.forEachRemaining(Consumer { 36 | assertEquals(expected.removeAt(0), it) 37 | }) 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /kotlinx-support-jdk8/src/test/kotlin/collections/ListTest.kt: -------------------------------------------------------------------------------- 1 | package kotlinx.support.jdk8.collections.test 2 | 3 | import kotlinx.support.jdk8.collections.* 4 | import org.junit.Test 5 | import kotlin.test.* 6 | import java.util.function.UnaryOperator 7 | 8 | 9 | class ListTest { 10 | 11 | @Test fun replaceAll() { 12 | val list = mutableListOf("ab", "cde", "x") 13 | list.replaceAll { it.length.toString() } 14 | 15 | val expected = listOf("2", "3", "1") 16 | assertEquals(expected, list) 17 | 18 | list.replaceAll(UnaryOperator.identity()) 19 | assertEquals(expected, list) 20 | } 21 | } -------------------------------------------------------------------------------- /kotlinx-support-jdk8/src/test/kotlin/collections/MapTest.kt: -------------------------------------------------------------------------------- 1 | package kotlinx.support.jdk8.collections.test 2 | 3 | import kotlinx.support.jdk8.collections.* 4 | import org.junit.Test 5 | import java.util.function.BiFunction 6 | import kotlin.test.* 7 | 8 | class MapTest { 9 | 10 | @Test fun getOrDefault() { 11 | val map = mapOf("x" to 1, "z" to null) 12 | assertEquals(1, map.getOrDefault("x", 0)) 13 | assertEquals(0, map.getOrDefault("y", 0)) 14 | assertEquals(null, map.getOrDefault("z", 0)) 15 | assertEquals(null, map.getOrDefault("y" as CharSequence, null)) 16 | } 17 | 18 | @Test fun forEach() { 19 | val map = mapOf("k" to "v") 20 | map.forEach { k, v -> 21 | assertEquals("k", k) 22 | assertEquals("v", v) 23 | } 24 | map.forEach { 25 | assertEquals("k", it.key) 26 | assertEquals("v", it.value) 27 | } 28 | } 29 | 30 | @Test fun replaceAll() { 31 | val map: MutableMap = mutableMapOf("a" to "b", "c" to "d") 32 | 33 | map.replaceAll { k, v -> k + v } 34 | assertEquals(mapOf("a" to "ab", "c" to "cd"), map) 35 | 36 | val operator = BiFunction { k, v -> k.toString() + v.toString() } 37 | map.replaceAll(operator) 38 | assertEquals(mapOf("a" to "aab", "c" to "ccd"), map) 39 | } 40 | 41 | @Test fun putIfAbsent() { 42 | val map = mutableMapOf(1 to "a") 43 | 44 | assertEquals("a", map.putIfAbsent(1, "b")) 45 | assertEquals("a", map[1]) 46 | 47 | assertEquals(null, map.putIfAbsent(2, "b")) 48 | assertEquals("b", map[2]) 49 | } 50 | 51 | 52 | @Test fun removeKeyValue() { 53 | val map = mutableMapOf(1 to "a") 54 | 55 | assertEquals(false, map.remove(1 as Number, null as Any?)) 56 | assertEquals(true, map.remove(1, "a")) 57 | } 58 | 59 | @Test fun replace() { 60 | val map = mutableMapOf(1 to "a", 2 to null) 61 | assertTrue(map.replace(2, null, "x")) 62 | assertEquals("x", map[2]) 63 | 64 | assertFalse(map.replace(2, null, "x")) 65 | 66 | assertEquals("a", map.replace(1, "b")) 67 | assertEquals(null, map.replace(3, "c")) 68 | 69 | } 70 | 71 | @Test fun computeIfAbsent() { 72 | val map = mutableMapOf(2 to "x", 3 to null) 73 | assertEquals("x", map.computeIfAbsent(2) { it.toString() }) 74 | assertEquals("3", map.computeIfAbsent(3) { it.toString() }) 75 | assertEquals(null, map.computeIfAbsent(0) { null }) 76 | } 77 | 78 | @Test fun computeIfPresent() { 79 | val map = mutableMapOf(2 to "x") 80 | assertEquals("2x", map.computeIfPresent(2) { k, v -> k.toString() + v }) 81 | assertEquals(null, map.computeIfPresent(3) { k, v -> k.toString() + v }) 82 | assertEquals(null, map.computeIfPresent(2) { k, v -> null }) 83 | assertFalse(2 in map) 84 | } 85 | 86 | @Test fun compute() { 87 | val map = mutableMapOf(2 to "x") 88 | assertEquals("2x", map.compute(2) { k, v -> k.toString() + v }) 89 | assertEquals(null, map.compute(2) { k, v -> null }) 90 | assertFalse { 2 in map } 91 | assertEquals("1null", map.compute(1) { k, v -> k.toString() + v }) 92 | } 93 | 94 | @Test fun merge() { 95 | val map = mutableMapOf(2 to "x") 96 | assertEquals("y", map.merge(3, "y") { old, new -> null }) 97 | assertEquals(null, map.merge(3, "z") { old, new -> 98 | assertEquals("y", old) 99 | assertEquals("z", new) 100 | null 101 | }) 102 | assertFalse(3 in map) 103 | 104 | val map2 = mutableMapOf(1 to null) 105 | // new value must be V!! 106 | assertFails { map2.merge(1, null) { k, v -> 2 } } 107 | } 108 | } -------------------------------------------------------------------------------- /kotlinx-support-jdk8/src/test/kotlin/collections/StreamsTest.kt: -------------------------------------------------------------------------------- 1 | package kotlinx.support.jdk8.streams.test 2 | 3 | import kotlinx.support.jdk8.streams.* 4 | import org.junit.Test 5 | import java.util.stream.* 6 | import kotlin.test.* 7 | 8 | class StreamsTest { 9 | 10 | @Test fun toList() { 11 | val data = arrayOf(1, 2L, 1.23, null) 12 | val streamBuilder = { Stream.of(*data) } 13 | 14 | assertEquals(data.asList(), streamBuilder().toList()) 15 | assertEquals(listOf(1), streamBuilder().filter { it is Int }.mapToInt { it as Int }.toList()) 16 | assertEquals(listOf(2L), streamBuilder().filter { it is Long }.mapToLong { it as Long }.toList()) 17 | assertEquals(listOf(1.23), streamBuilder().filter { it is Double }.mapToDouble { it as Double }.toList()) 18 | } 19 | 20 | 21 | @Test fun asSequence() { 22 | val data = arrayOf(1, 2L, 1.23, null) 23 | 24 | fun assertSequenceContent(expected: List, actual: Sequence) { 25 | assertEquals(expected, actual.toList()) 26 | assertFailsWith ("Second iteration fails") { actual.toList() } 27 | 28 | } 29 | 30 | assertSequenceContent(data.asList(), Stream.of(*data).asSequence()) 31 | assertSequenceContent(listOf(1, 2), IntStream.of(1, 2).asSequence()) 32 | assertSequenceContent(listOf(1L, 2L), LongStream.of(1L, 2L).asSequence()) 33 | assertSequenceContent(listOf(1.0, 2.0), DoubleStream.of(1.0, 2.0).asSequence()) 34 | } 35 | 36 | @Test fun asStream() { 37 | val sequence = generateSequence(0) { it -> it * it + 1 } 38 | val stream = sequence.asStream() 39 | val expected = Stream.iterate(0) { it -> it * it + 1 } 40 | 41 | assertEquals(expected.limit(7).toList(), stream.limit(7).toList()) 42 | } 43 | 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /kotlinx-support-jdk8/src/test/kotlin/text/CharSequenceTest.kt: -------------------------------------------------------------------------------- 1 | package kotlinx.support.jdk8.text.test 2 | 3 | import kotlinx.support.jdk8.text.* 4 | import org.junit.Test 5 | import java.util.stream.Collectors 6 | import kotlin.test.* 7 | 8 | class CharSequenceTest { 9 | @Test fun chars() { 10 | val string = "test" 11 | 12 | val chars = string.chars().boxed().collect(Collectors.mapping({ it.toChar()}, Collectors.toList())) 13 | 14 | assertEquals(string.toList(), chars) 15 | } 16 | 17 | 18 | @Test fun codePoints() { 19 | val dth54 = "\uD83C\uDC58" // domino tile horizontal 5-4 20 | val dth55 = "\uD83C\uDC59" // domino tile horizontal 5-5 21 | 22 | val seq = "$dth54$dth55" as CharSequence 23 | 24 | val codePoints = seq.codePoints().toArray() 25 | assertEquals(listOf(0x1F058, 0x1F059), codePoints.toList()) 26 | } 27 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | org.jetbrains.kotlinx 9 | kotlinx-support 10 | 0.1-SNAPSHOT 11 | pom 12 | 13 | Kotlin JDK support libraries 14 | Extension and top-level functions to use JDK7/JDK8 features in Kotlin 1.0 15 | https://github.com/Kotlin/kotlinx.support/ 16 | 17 | 18 | 19 | The Apache Software License, Version 2.0 20 | http://www.apache.org/licenses/LICENSE-2.0.txt 21 | repo 22 | A business-friendly OSS license 23 | 24 | 25 | 26 | 27 | https://github.com/Kotlin/kotlinx.support 28 | scm:git:https://github.com/Kotlin/kotlinx.support.git 29 | scm:git:https://github.com/Kotlin/kotlinx.support.git 30 | 31 | 32 | 33 | 34 | JetBrains 35 | JetBrains Team 36 | JetBrains 37 | http://www.jetbrains.com 38 | 39 | 40 | 41 | 42 | UTF-8 43 | 1.0.2 44 | 4.12 45 | 1.6 46 | 1.6 47 | 48 | 49 | 50 | 51 | 52 | 3.0.2 53 | 54 | 55 | 56 | 57 | bintray 58 | https://api.bintray.com/maven/kotlin/kotlinx.support/kotlinx.support 59 | 60 | 61 | 62 | 63 | kotlinx-support-jdk7 64 | kotlinx-support-jdk8 65 | 66 | 67 | 68 | 69 | org.jetbrains.kotlin 70 | kotlin-stdlib 71 | ${kotlin.version} 72 | compile 73 | 74 | 75 | junit 76 | junit 77 | ${junit.version} 78 | test 79 | 80 | 81 | org.jetbrains.kotlin 82 | kotlin-test-junit 83 | ${kotlin.version} 84 | test 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | org.jetbrains.kotlin 93 | kotlin-maven-plugin 94 | ${kotlin.version} 95 | 96 | 97 | org.apache.maven.plugins 98 | maven-source-plugin 99 | 2.4 100 | 101 | 102 | org.apache.maven.plugins 103 | maven-release-plugin 104 | 2.5.2 105 | 106 | 107 | 108 | 109 | 110 | 111 | maven-source-plugin 112 | 113 | 114 | 115 | 116 | package 117 | attach-sources 118 | 119 | jar-no-fork 120 | 121 | 122 | 123 | 124 | 125 | 126 | org.jetbrains.kotlin 127 | kotlin-maven-plugin 128 | 129 | 130 | compile 131 | compile 132 | 133 | compile 134 | 135 | 136 | 137 | test-compile 138 | test-compile 139 | 140 | test-compile 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | --------------------------------------------------------------------------------