CharBuffer to string? - kotlin

How to get the string "hi" from the CharBuffer? toString() does not seem to work.
val a = CharBuffer.allocate(10);
a.put('h');
a.put('i');
val b = a.toString();
Variable states after running the code above:

CharBuffer is pretty low-level and really meant for I/O stuff, so it may seem illogical at first. In your example it actually returned a string containing remaining 8 bytes that you didn't set. To make it return your data you need to invoke flip() like this:
val a = CharBuffer.allocate(10);
a.put('h');
a.put('i');
a.flip()
val b = a.toString();
You can find more in the docs of the Buffer
For more typical use cases it is much easier to use StringBuilder:
val a = StringBuilder()
a.append('h')
a.append('i')
val b = a.toString()
Or even use a Kotlin util that wraps StringBuilder:
val b = buildString {
append('h')
append('i')
}

Related

Why am I geting a blank when I run this string funtion in Kotlin?

So I was solving a problem that required me to put unique characters in a string without using a data structure.
fun main(){
val s1 = "fhfnfnfjuw"
val s2 = "Osayuki"
val s3 = "Raymond"
val s4 = "Aseosa"
uniqueChar(s1)
}
fun uniqueChar(s: String){
val updatedString = ""
s.forEach {c ->
if (!updatedString.contains(c)){
updatedString.plus(c)
}
}
println(updatedString)
}
And getting this error
I'm not sure what's going on and why I'm getting a blank. I'm sure it's an easy fix, but I can't see it. Any help is appreciated.
updatedString.plus(c) does not change updatedString. It creates a new string, including the character c. Since you don't do anything with that, the new string goes...nowhere.
Instead, you probably wanted updatedString = updatedString.plus(c) -- or something better with StringBuilder, but that's the closest version to your code.

Is there a way to lazy-init a costly field in a specific constructor?

I have a data class I want to populate, where in one constructor I have the data already, and in another I would like to fetch it only when it is required, which is rare.
A sample code would be:
data class Source1(val str1: String)
data class Source2(val str2: String)
data class DTO(val data1: String, val data2: String) {
// ctor which does not need laziness
constructor(source1: Source1) : this(
data1 = source1.str1,
data2 = source1.str1
)
// ctor which needs costly data
constructor(source2: Source2, costlyData: String) : this(
data1 = source2.str2,
data2 = costlyData
)
}
fun demo() {
val source1 = Source1("some str - 1")
DTO(source1)
val source2 = Source2("some str - 2")
val costlyData: String = costlyOperation() // this is the operation I'd like to execute lazily
DTO(source2, costlyData)
}
I'd say the easiest way would be to accept a function as a constructor parameter, something like this:
class DTO(provider:()->String){
constructor(data: String):this({data})
val data by lazy{ provider()}
}
So you can use it in both ways:
val eager = DTO("some str - 1")
val lazy = DTO(::costlyOperation)
A bit nicer way is to have a Source abstraction with different implementations for providing a constant value and performing an operation. But the overall idea would be the same.
Although I wouldn't call this DTO anymore and it loses its data class capabilities regarding the content.

How to get String description/value?

In Kotlin, how to get the raw value of the String?
For example,
val value: String = "Adrian"
Expected result:
"Cannot find value: Adrian"
I am coming from Swift and I know in swift it works like this
let value: String = "Adrian"
print("Cannot find \(string.description): \(value)")
Another example in Swift,
let a: String = "b"
print("\(a.description) = \(a)"
///prints "a = b"
Im guessing a String extension is needed given I read the Kotlin String documentation and seems none of the choices provides the expected result.
A simple problem but I really can't solve it:(
This might help you. For this you have to use Kotlin reflection:
Example:
data class Person(val name:String)
fun main(){
val person = Person("Birju")
val prop = person::name
println("Property Name: ${prop.name}")
println("Property Value: ${prop.get()}")
}
How about
println("value :$value")
You don't need concatination operator(+) to concat strings in kotlin

How should I define these complex initializer for a property

Although I checked all tests in the kotlinpoet code, but I didn't find a proper way to implement below target codes, or I am not sure whether I used the best approach to do that. If anyone can provide some comments about this, that would be highly appreciate.
These properties are defined in the function of a class
Target Code 1
val outputState = StateType1(iouValue, ourIdentity, otherParty)
I used below codes to generate above code
.addCode(CodeBlock.of("%L",
PropertySpec.builder("outputState", ClassName("","StateType1"))
.initializer(CodeBlock.of("%T(%L, %L, %L)", ClassName("","StateType1"), "iouValue", "ourIdentity", "otherParty"))
.build()))
But question would be this outputState might be from different types, for example, StateType1 has 3 parameters, but StateTyp2 might only has 1 parameter, how should I dynamically define my kotlinpoet code to generate correct target code.
Target Code 2
val txBuilder = TransactionBuilder(notary = notary)
.addOutputState(outputState, TEMPLATE_CONTRACT_ID)
I didn't find a reference test case which has this scenario, after property's initializer then invoke it's function directly.
Use CodeBlock.Builder for the first example, it gives you more flexibility in constructing CodeBlocks:
fun createConstructorCall(type: TypeName, vararg args: String): CodeBlock {
val argsCode = args
.map { CodeBlock.of("%L", it) }
.joinToCode(separator = ", ", prefix = "(", suffix = ")")
return CodeBlock.Builder()
.add("%T", type)
.add(argsCode)
.build()
}
val className = ClassName("", "StateType1")
val codeBlock = CodeBlock.of("%L", PropertySpec.builder("outputState", className)
.initializer(createConstructorCall(className, "iouValue", "ourIdentity", "otherParty"))
.build())
assertThat(codeBlock.toString()).isEqualTo("""
|val outputState: StateType1 = StateType1(iouValue, ourIdentity, otherParty)
|""".trimMargin())
In the second example, we don't really provide anything special, pass your code as a String and feel free to use placeholders to parameterize if needed:
val className1 = ClassName("", "TransactionBuilder")
val codeBlock1 = CodeBlock.of("%L", PropertySpec.builder("txBuilder", className)
.initializer(
"%T(notary = notary)\n.addOutputState(outputState, TEMPLATE_CONTRACT_ID)",
className1)
.build())
assertThat(codeBlock1.toString()).isEqualTo("""
|val txBuilder: StateType1 = TransactionBuilder(notary = notary)
| .addOutputState(outputState, TEMPLATE_CONTRACT_ID)
|""".trimMargin())

Kotlin: how to swap character in String

I would like to swap a string from "abcde" to "bcdea". So I wrote my code as below in Kotlin
var prevResult = "abcde"
var tmp = prevResult[0]
for (i in 0..prevResult.length - 2) {
prevResult[i] = prevResult[i+1] // Error on preveResult[i]
}
prevResult[prevResult.length-1] = tmp // Error on preveResult[prevResult.lengt-1]
It errors out as stated above comment line. What did I do wrong? How could I fix this and get what I want?
Strings in Kotlin just like in Java are immutable, so there is no string.set(index, value) (which is what string[index] = value is equivalent to).
To build a string from pieces you could use a StringBuilder, construct a CharSequence and use joinToString, operate on a plain array (char[]) or do result = result + nextCharacter (creates a new String each time -- this is the most expensive way).
Here's how you could do this with StringBuilder:
var prevResult = "abcde"
var tmp = prevResult[0]
var builder = StringBuilder()
for (i in 0..prevResult.length - 2) {
builder.append(prevResult[i+1])
}
builder.append(tmp) // Don't really need tmp, use prevResult[0] instead.
var result = builder.toString()
However, a much simpler way to achieve your goal ("bcdea" from "abcde") is to just "move" one character:
var result = prevResult.substring(1) + prevResult[0]
or using the Sequence methods:
var result = prevResult.drop(1) + prevResult.take(1)
You can use drop(1) and first() (or take(1)) to do it in one line:
val str = "abcde"
val r1 = str.drop(1) + str.first()
val r2 = str.drop(1) + str.take(1)
As to your code, Kotlin String is immutable and you cannot modify its characters. To achieve what you want, you can convert a String to CharArray, modify it and then make a new String of it:
val r1 = str.toCharArray().let {
for (i in 0..it.lastIndex - 1)
it[i] = it[i+1]
it[it.lastIndex] = str[0] // str is unchanged
String(it)
}
(let is used for conciseness to avoid creating more variables)
Also, you can write a more general version of this operation as an extension function for String:
fun String.rotate(n: Int) = drop(n % length) + take(n % length)
Usage:
val str = "abcde"
val r1 = str.rotate(1)
Simpler solution: Just use toMutableList() to create a MutableList of Char and then join it all together with joinToString.
Example:
Given a String input, we want to exchange characters at positions posA and posB:
val chars = input.toMutableList()
val temp = chars[posA]
chars[posA] = chars[posB]
chars[posB] = temp
return chars.joinToString(separator = "")
Since Strings are immutable, you will have to copy the source string into an array, make changes to the array, then create a new string from the modified array. Look into:
getChars() to copy the string chars into an array.
Perform your algorithm on that array, making changes to it as needed.
Convert the modified array back into a String with String(char[]).