As a software developer working in a tactical business environment, I'm always looking for ways to do more with less code. Even better, if I can modify and scale code to constantly adapt to business demands then I have to do less code re-writes.
Java has been my go-to language as it is practical, scalable, performant, portable, and statically-typed. As I became proficient and took on more ambitious projects, it started to feel cumbersome (and I kept eyeing C# wishfully). Thankfully I found RxJava last year, and reactive programming enabled me to take on tasks that I would hesitate to do before.
Utilizing RxJava almost exclusively for all my projects, I became much more productive and the quality of my applications increased. But I slowly started to realize the limitations of the Java language were holding RxJava back. Even with Java 8's lambdas, some functional programming tasks became very verbose.
For instance, using the compose()
operator which accepts a custom Transformer
allows you to create your own operator with existing RxJava operators. The problem is it can quickly become wordy and less fluid.
Here is a simple example. I can create a custom Transformer
that turns an Observable<T>
into an Observable<ImmutableList<T>>
since I like Google Guava's immutable collections.
public final class Launcher {
public static void main(String[] args) {
Observable<String> source = Observable.just("Alpha",
"Beta", "Gamma", "Delta", "Epsilon");
source.compose(toImmutableList()).subscribe(System.out::println);
}
public static <T> Observable.Transformer<T,ImmutableList<T>> toImmutableList() {
return obs -> obs.collect(() -> ImmutableList.<T>builder(),
(b,t) -> b.add(t)).map(b -> b.build());
}
}
With Java 8 this is not a very big deal. But this Transformer
factory exists in the same class, and if I stored it in a separate factory class it would slowly start getting verbose.
public final class Launcher {
public static void main(String[] args) {
Observable<String> source = Observable.just("Alpha", "Beta", "Gamma",
"Delta", "Epsilon");
source.compose(GuavaTransformers.toImmutableList()).subscribe(System.out::println);
}
/*This would be in the GuavaTransformers class */
public static <T> Observable.Transformer<T,ImmutableList<T>> toImmutableList() {
return obs -> obs.collect(() -> ImmutableList.<T>builder(),
(b,t) -> b.add(t)).map(b -> b.build());
}
}
Even worse if I start to create more complicated Transformers or Operators with arguments, my compose()
statement can start to get pretty ugly. If I wanted to collect items into an ImmutableListMultimap
, it starts to get less fluid with the lambda arguments.
public final class JavaLauncher {
public static void main(String[] args) {
Observable<String> source = Observable.just("Alpha", "Beta", "Gamma",
"Delta", "Epsilon");
source.compose(GuavaTransformers
.toImmutableListMultiMap(s -> s.length())).subscribe(System.out::println);
}
/*This would be in the GuavaTransformers class */
public static <T> Observable.Transformer<T,ImmutableList<T>> toImmutableList() {
return obs -> obs.collect(() -> ImmutableList.<T>builder(),
(b,t) -> b.add(t)).map(b -> b.build());
}
public static <T,K> Observable.Transformer<T,ImmutableListMultimap<K,T>>
toImmutableListMultiMap(Func1<T,K> keyMapper) {
return obs -> obs.collect(() -> ImmutableListMultimap.<K,T>builder(),
(b,t) -> b.put(keyMapper.call(t), t)).map(b -> b.build());
}
}
These may be trivial examples, but for larger applications these problems can quickly become amplified. Precious code real estate becomes eaten away even with the efficiencies of RxJava and Java 8 lambdas, and we have not even gotten to the subject of Tuples and data classes! But Kotlin solves all of these problems and more.
Introducing Kotlin
I tried looking at Scala, Python, and other languages. I especially looked at Scala but despite all the praise it gets, I found it too esoteric. Then one day I found JetBrains sharing their new language called Kotlin. They advertised it as an industry-grade, business-focused language emphasizing practicality rather than convention. JetBrains, the creator of the popular Java IDE Intellij IDEA, built it because they felt they could be more productive using a language that Java should have been. After studying Kotlin and re-writing two home projects with it, I quickly became sold and am ready to use it exclusively. The fact it is 100% interoperable with Java and all Java libraries made it a quick sell as well.
But in this post, what I really want to share is my experience using RxJava with Kotlin. Ironically, I found RxJava works better with Kotlin than Java itself. It just expresses functional programming concepts so much better.
For instance, I can "add" methods to the Observable
using extension methods, without even extending the class! This is nothing new if you came from a C# background, but this was always the #1 thing I wished Java would have. Below I add toImmutableList()
and toImmutableListMultimap()
methods to the Observable
(in Kotlin methods are actually called functions). I can then call those methods directly on the Observable
rather than creating a compose()
statement.
fun main(args: Array<String>) {
val source = Observable.just("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
source.toImmutableListMultimap { it.length }.subscribe { println(it) }
}
fun <T> Observable<T>.toImmutableList() =
collect({ ImmutableList.builder<T>()},{ b, t -> b.add(t)}).map { it.build() }
inline fun <K,T> Observable<T>.toImmutableListMultimap(
crossinline keyMapper: (T) -> K) = collect({ ImmutableListMultimap.builder<K,T>()},
{ b, t -> b.put(keyMapper(t), t)}).map { it.build() }
There are a lot of observations to make here.
We did not have to wrap these functions inside a class. Unlike Java, Kotlin does not force you to put static methods in a class. This is really helpful and helps eliminate a lot of boilerplate, especially for procedural programs.
The type of the
source
variable is inferred, allowing us to not have to explicitly declare it as anObservable<String>
. You can do that if you want to as shown below. In Kotlin the type comes after the variable name (separated by a colon:
). This is done because the variable name is likely more pertinent to you than the type, so it is declared first to making finding it easy.val source: Observable<String> = Observable.just("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
You can express lambdas much more easily. Instead of having to write out a lambda for a simple one-to-one mapping like
s -> s.length()
, you can express this with a much more succintit.length
, whereit
refers to the single incoming item emitted (this is featured in other JVM languages). Also, there are no paranthesis()
to receive functional arguments. Instead you use curley braces{}
and express the entire function for that operator in it. This is especially helpful because you can put multiple lines in the curly braces{ }
at any time.source.toImmutableListMultimap { it.length }.subscribe{ println(it)}
You can "add" functions/methods to a class without actually extending a class using extension functions. This single statement below adds a
toImmutableList()
function to theObservable
everywhere in your application (unless you make itprivate
or alter its scope). How is this done? The compiler simply makes it astatic
method when turned into bytecode, but you get the nice syntactic sugar as well as seeing it in your auto-complete. You do not have to target generic types either with extension methods. For example, I could make aconcatStr()
extension method specifically targetingObservable<String>
and notObservable<T>
.fun <T> Observable<T>.toImmutableList() = collect({ ImmutableList.builder<T>()},{ b, t -> b.add(t)}).map { it.build()}
Functional argument types are much simpler. Instead of expressing a functional type as
Func1<T,K>
, you can use a SAM-less type expression(T) -> K
. This gets across much more easily that this function receives aT
and turns it into aK
. It is not a single-abstract-method type (SAM) which makes it easier to reason with and leaves out the question "which single-method interface am I using?". Of course, Kotlin will handle converting lambdas to SAM when calling Java libraries, but it will not do it in Kotlin. Also, using theinline
andcrossinline
keywords for a function accepting function arguments, you can get great efficiency by eliminating object overhead.inline fun <K,T> Observable<T>.toImmutableListMultimap( crossinline keyMapper: (T) -> K) = collect({ImmutableListMultimap.builder<K,T>()}, { b, t -> b.put(keyMapper(t), t)}).map { it.build() }
Data Classes
Another great feature of Kotlin is data classes. Have you ever wanted to simply zip two values together, but had to create an entire class just to pair them up with hashCode()
, equals()
, and toString()
implemented?
public final class JavaLauncher {
public static void main(String[] args) {
Observable<String> letter = Observable.just("Alpha", "Beta", "Gamma",
"Delta", "Epsilon");
Observable<Integer> number = Observable.just(1,2,3,4,5);
Observable<CodePair> zipped = Observable.zip(letter,number,
(l,n) -> new CodePair(l,n));
zipped.subscribe(System.out::println);
}
private static final class CodePair {
private final String letter;
private final Integer number;
CodePair(String letter, Integer number) {
this.letter = letter;
this.number = number;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CodePair codePair = (CodePair) o;
if (!letter.equals(codePair.letter)) return false;
return number.equals(codePair.number);
}
@Override
public int hashCode() {
int result = letter.hashCode();
result = 31 * result + number.hashCode();
return result;
}
@Override
public String toString() {
return "CodePair{" +
"letter='" + letter + '\'' +
", number=" + number +
'}';
}
}
}
It is not fun I had to write 36 lines of code just to create a CodePair
class holding two properties. This problem comes up in functional programming quite a bit, and the only alternative is creating esoteric tuples which only obfuscate the code.
But in Kotlin, you can declare something called a data class. This allows you to quickly declare a class in one line with all its properties, and it will take care of the hashCode()
, equals()
, toString()
and even clone/modify builders for you.
That 48-line mess in Java now becomes 5 lines in Kotlin.
fun main(args: Array<String>) {
data class CodePair(val letter: String, val number: Int)
val letter = Observable.just("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
val number = Observable.just(1, 2, 3, 4, 5)
val zipped = Observable.zip(letter, number) { l, n -> CodePair(l, n) }
zipped.subscribe { System.out.println(it) }
}
We declared a CodePair
class right inside the main()
function, and it only exists in the scope of the main()
function. It has named properties letter
and number
you can access. This opens up a lot of tactical possibilities that were borderline impractical to do in Java. Being able to declare simple classes on the fly and have the common method implementations done allows fast, organized, and legible code to be developed quickly.
Conclusions
I have only scratched the surface in sharing what Kotlin can do, with or without RxJava. This was not a tutorial but just a quick showcase of how RxJava expresses differently in Kotlin. I hope I have effectively shared my experience and you are curious to check out Kotlin. I know Scala can do quite a bit with RxScala, but Kotlin is different. It really serves folks who need the tactical abilities and simplicity of Python with the scalability and power of Java. When you throw RxJava into the mix with Kotlin, I have found it to be a very rewarding combination. Did I forget to mention that there are no primitives or boxed types either? There are so many features in Kotlin that would be out of scope to post here, like nullable types
As a sidenote, Kotlin is supported on Android. You can also checkout the RxKotlin library which extends RxJava to take advantage of Kotlin functionalities (such as adding toObservable()
methods to collections).
This concise code comes at a huge cost. Only you know what it does and it is hideously ugly. That bunch of single letter variables, scattered through a field of dashes, arrows and commas is absolutely impossible to understand, if you aren't the one who wrote this write-only code. No explanatory variables, no intent through naming, a huge amount of mental mapping is needed in order to comprehend what the idea of that code is. It would be a pain to work with such a code base. I hope this doesn't catch on. I want to work with readable, self-explanatory, clean code. Not the less-characters-possible code
ReplyDeleteDo you feel the same way about Scala or even lambdas altogether? Just curious as FP might not even be your thing...
DeleteVariable naming is on the hand of the programmer, Java/Kotlin does not interfere with them.
DeleteI guess the 'mental mapping' you mentioned is partly because of the noise of Rx & Guava usage.
I'd suggest having a look at Kotlin itself on its own (if you haven't heard of that). It opens up many possibilities.
This article is rather a non beginner as a Kotlin intro though.
Pretty damn clear... what l and n are there
Delete
DeleteGreat Article
IEEE final year projects on machine learning
JavaScript Training in Chennai
Final Year Project Centers in Chennai
JavaScript Training in Chennai
Thanks Hoang, you are correct. This article was written for an audience already familiar with RxJava and functional programming, and show how Kotlin can solve some problems they likely have encountered. It id by no means an introduction to Kotlin or functional programming. JetBrains has some great online documentation for Java devs to learn Kotlin in a few hours at kotlinlang.org
ReplyDeleteJava exceptions provide a way to process synchronous errors such as divisions by zero and out-of-range array indexes, and this article offers top practical guidelines on their use. The article includes when to use Exceptions, when you neither catch nor throw exceptions and (importantly) when to use standard Java exceptions. See more assignment help programming
ReplyDelete
ReplyDeleteGreat Content, Just loved the way you presented it… Keep up the good work Cheap Paraphrasing Services
This is an informative blog. Keep it up. I am looking forward to this kind of blog. Thanks for sharing it with us norton.com/setup
ReplyDeleteThank you for sharing this blog, It is an amazing blog, I am really impressed by your blog, It’s really useful norton.com/setup
ReplyDeletewww.norton.com/setup
There are many blogs I have read But when I read Your Blogs I have found such useful information, fresh content with such amazing editing everything is superb in your blog, Thank you so much for sharing this useful and informative information with us. Wish you all the best for upcoming comments. And I have also few informative links which I am going share here. wwww.norton.com/setup enter product key
ReplyDeletewww.norton.com/setup, Norton product key, Norton Setup, norton.com/setup
I really happy found this website eventually. Really informative and inoperative, Thanks for the post and effort! Please keep sharing more such blog.
ReplyDeleteoffice.com/setup
www.office.com/setup
office setup
mcafee.com/activate
www.mcafee.com/activate
bitcoin login
Great share!
ReplyDeleteLoved all that you shared, and you are right, one cannot deny the power of Google. I simply love it and am part of a number of
communities too. The point you mention in your post Sand blasting machine works that are very useful for me. I understand the way of the attractive to the customer with the products.
Keep it works and share with us your latest information. For more Information or any help then visit now at Sand Blasting Machine, Sand Blasting Machine for Sale, Sand Blasting Machine Manufacturer, and Small Sand Blasting Machine.
They are similar to small communities that you own - check them out if you haven't already.It's all got a lot better than before!t.
Thanks for sharing. Have a nice week ahead.
Visit at :www.blaster.co.in
Regards,
Purnima Sharma.
Săn vé máy bay tại Aivivu, tham khảo
ReplyDeletevé máy bay đi Mỹ bao nhiêu
bay từ mỹ về việt nam
đặt vé máy bay từ nhật về việt nam
chuyến bay từ canada về việt nam
Xmedia Solutions
ReplyDeleteXmedia Solution About us in usa
Xmedia Solution infrastructure in usa
Xmedia Solution Career in usa
Xmedia Solution Contact us in usa
Thanks For Sharing Such An Amazing Post Enjoyed Reading it.
ReplyDeleteRegards
www.primevideo.com/mytv
www.primevideo/mytv
www.primevideo.com/mytv
www.amazon.com/mytv
amazon.com/mytv
amazon.com/mytv
www.netflix.com/activate
Great content & thanks for sharing with best digital marketing company in dehradun
ReplyDeleteWe declared a CodePair class right inside the main() function, and it only exists in the scope of the main() function. It has named properties letter and number you can access. This opens up a lot of tactical possibilities that were borderline impractical to do in Java. Being able to declare simple classes on the fly and have the common method implementations done allows fast, organized, and legible code to be developed quickly. swarovski necklace wholesale uk , gold chain canada
ReplyDeletegoogle 3983
ReplyDeletegoogle 3984
google 3985
google 3986
google 3987
google 3988
Great Share!
ReplyDeleteFirst off, congratulations on this post. If You are searching for latest government jobs in India. Vacancysquare provides you upcoming government jobs information like - Railway, Police, Banking Job, Defense, SSC, UPSC, UPSSSC, teacher jobs and other department for state and central government job. This bucket list for you to know the right jobs detail.
This is really awesome but that's what you always crank out my friend. Reading your story got my face leaking and my heart singing. Find qualification based government job and vacancies with employment news at: "www.vacancysquare.com". Also check govt jobs, private jobs, latest jobs, teacher jobs, bank jobs, railway jobs, police jobs, UPSC jobs, SSC jobs, UPSSSC jobs, sarkari result with employment news.
Great posts we can share to our users. Check the latest government job vacancies, upcoming government Indian jobs, latest notifications for government jobs, today government jobs notifications or sarkari naukri now. Just visit our website www.vacancysquare.com to get your dream job notification today.
Get a complete information about Government jobs in India, Latest jobs in India, Work from home jobs, admit card, exams, results, answer key, admission and syllabus of Govt Indian jobs.
If you are interested in free guest post, advertising with us, writing for us and paid guest post service to contact us & about OR visit on our job notification portal www.vacancysquare.com.
All the best, I’m excited to watch your journey! Keep it works and share your amazing thoughts.
Great share and thanks again for the mention here,
Thanks and Regards!
Priya Singh.
Enjoyed reading your post keep sharing such amazing post will come back to read more.
ReplyDeleteRegards
office.com/setup
office.com/setup home & student 2019
fubo.tv/connect
www.fubo.tv/connect
www.primevideo.com/mytv
primevideo.com/mytv
best payroll software for small business
ReplyDeletebest cloud payroll software
This blog is very useful and important for all of us. Capital Athena is a luxury residential project.
ReplyDeleteYou can buy luxury apartment in Capital Athena Noida Extension.
I would like to take this opportunity to thank the author for his incredible work. I believe Customer relationship management is essential for every business to create a loyal customer base. keep doing it. all the best
ReplyDeleteBest CRM Software in India
very nice blog thank you
ReplyDeleteRudraksha Beads
Rudraksha Bracelet
thanks for excellent blog
ReplyDeletevaraha statue
hanuman murti
nice bolg thanks for information
ReplyDeletetulsi mala
spiritual gifts wholesale
Thank you for providing this blog really appreciate the efforts you have taken into curating this article if you want you can check out data science course in bangalore they have a lot to offer with regards to data science in terms of training and live projects.
ReplyDeleteI really happy found this website eventually. Really informative and inoperative, Thanks for the post and effort! Please keep sharing more such blog.
ReplyDeletebitcoin login
bitcoin login
gemini login
gemini login
bitcoin login
bitcoin login
bitcoin login
keep sharing more information
ReplyDeleteGoogle Advertisement