What are the most common mistakes that Java developers make when migrating to Scala?
By mistakes I mean writing a code that does not conform to Scala spirit, for example using loops when map-like functions are more appropriate, excessive use of exceptions etc.
EDIT: one more is using own getters/setters instead of methods kindly generated by Scala
It's quite simple: Java programmer will tend to write imperative style code, whereas a more Scala-like approach would involve a functional style.
That is what Bill Venners illustrated back in December 2008 in his post "How Scala Changed My Programming Style".
That is why there is a collection of articles about "Scala for Java Refugees".
That is how some of the SO questions about Scala are formulated: "help rewriting in functional style".
One obvious one is to not take advantage of the nested scoping that scala allows, plus the delaying of side-effects (or realising that everything in scala is an expression):
public InputStream foo(int i) {
final String s = String.valueOf(i);
boolean b = s.length() > 3;
File dir;
if (b) {
dir = new File("C:/tmp");
} else {
dir = new File("/tmp");
}
if (!dir.exists()) dir.mkdirs();
return new FileInputStream(new File(dir, "hello.txt"));
}
Could be converted as:
def foo(i : Int) : InputStream = {
val s = i.toString
val b = s.length > 3
val dir =
if (b) {
new File("C:/tmp")
} else {
new File("/tmp")
}
if (!dir.exists) dir.mkdirs()
new FileInputStream(new File(dir, "hello.txt"))
}
But this can be improved upon a lot. It could be:
def foo(i : Int) = {
def dir = {
def ensuring(d : File) = { if (!d.exists) require(d.mkdirs); d }
def b = {
def s = i.toString
s.length > 3
}
ensuring(new File(if (b) "C:/tmp" else "/tmp"));
}
new FileInputStream(dir, "hello.txt")
}
The latter example does not "export" any variable beyond the scope which it is needed. In fact, it does not declare any variables at all. This means it is easier to refactor later. Of course, this approach does lead to hugely bloated class files!
A couple of my favourites:
It took me a while to realise how truly useful Option is. A common mistake carried from Java is to use null to represent a field/variable that sometimes does not have a value. Recognise that you can use 'map' and 'foreach' on Option to write safer code.
Learn how to use 'map', 'foreach', 'dropWhile', 'foldLeft', ... and other handy methods on Scala collections to save writing the kind of loop constructions you see everywhere in Java, which I now perceive as verbose, clumsy, and harder to read.
A common mistake is to go wild and overuse a feature not present in Java once you "grokked" it. E.g. newbies tend to overuse pattern matching(*), explicit recursion, implicit conversions, (pseudo-) operator overloading and so on. Another mistake is to misuse features that look superficially similar in Java (but ain't), like for-comprehensions or even if (which works more like Java's ternary operator ?:).
(*) There is a great cheat sheet for pattern matching on Option: http://blog.tmorris.net/scalaoption-cheat-sheet/
I haven't adopted lazy vals and streams so far.
In the beginning, a common error (which the compiler finds) is to forget the semicolon in a for:
for (a <- al;
b <- bl
if (a < b)) // ...
and where to place the yield:
for (a <- al) yield {
val x = foo (a).map (b).filter (c)
if (x.cond ()) 9 else 14
}
instead of
for (a <- al) {
val x = foo (a).map (b).filter (c)
if (x.cond ()) yield 9 else yield 14 // why don't ya yield!
}
and forgetting the equals sign for a method:
def yoyo (aka : Aka) : Zirp { // ups!
aka.floskel ("foo")
}
Using if statements. You can usually refactor the code to use if-expressions or by using filter.
Using too many vars instead of vals.
Instead of loops, like others have said, use the list comprehension functions like map, filter, foldLeft, etc. If there isn't one available that you need (look carefully there should be something you can use), use tail recursion.
Instead of setters, I keep the spirit of functional programming and have my objects immutable. So instead I do something like this where I return a new object:
class MyClass(val x: Int) {
def setX(newx: Int) = new MyClass(newx)
}
I try to work with lists as much as possible. Also, to generate lists, instead of using a loop, use the for/yield expressions.
Using Arrays.
This is basic stuff and easily spotted and fixed, but will slow you down initially when it bites your ass.
Scala has an Array object, while in Java this is a built in artifact. This means that initialising and accessing elements of the array in Scala are actually method calls:
//Java
//Initialise
String [] javaArr = {"a", "b"};
//Access
String blah1 = javaArr[1]; //blah1 contains "b"
//Scala
//Initialise
val scalaArr = Array("c", "d") //Note this is a method call against the Array Singleton
//Access
val blah2 = scalaArr(1) //blah2 contains "d"
Related
I'm learning Java for the first time (my prior experience is Python and Haskell). I have a situation that would, in Python, require a "decorate and sort" idiom. Such as the following (code not tested but this is roughly correct):
origList = <something>
decorated = sorted( [(evalFunc(item), item) for item in origList] )
finalList = [item for _, item in decorated]
By choosing a different evalFunc you can choose how this is sorted.
In Java, I'm writing a program that composes music by choosing from among a list of notes, evaluating the "fitness" of each note, and picking the best. I have a class representing musical notes:
class Note {
...
}
I have a class that represents the fitness of a note as two values, its goodness and badness (yes, these are separate concepts in my program). Note: in Python or Haskell, this would simply be a 2-tuple, but my understanding is that Java doesn't have tuples in the usual sense. I could make it a pair, but it gets unwieldy to declare variables all over the place like List<Pair<Type1,Pair<Type2,Type3>>>. (As an aside, I don't think Java has type aliases either, which would let me shorten the declarations.)
class Fitness {
double goodness;
double badness;
}
The function that evaluates the fitness needs access to several pieces of data other than the Note. We'll say it's part of a "Composition" class:
class Composition {
... data declared here ... ;
public Fitness evaluate(Note n) {
}
}
I'd like to be able to compare Fitness objects in numerical order. There are two ways to compare: either goodness or badness can be numerically compared, depending on the situation.
class CompareFitnessByGoodness implements Comparator<Fitness> {
}
class CompareFitnessByBadness implements Comparator<Fitness> {
}
I'd like to package the Note together with its fitness, so I can sort the combined list by fitness and later pull out the best Note.
class Together {
public Note;
public Fitness;
}
I'd like to sort a List<Together> by either the goodness, or by the badness. So I might need:
class CompareTogetherByGoodness implements Comparator<Together> {
...
}
class CompareTogetherByBadness implements Comparator<Together> {
...
}
Eventually I'll write something like
Note pickBest(List<Together> notes) {
// Pick a note that's not too bad, and pretty good at the same
// time.
// First sort in order of increasing badness, so I can choose
// the bottom half for the next stage (i.e. the half "least bad"
// notes).
Collections.sort(notes, new CompareTogetherByBadness());
List<Together> leastBadHalf = notes.subList(0, notes.size()/2);
// Now sort `leastBadHalf` and take the last note: the one with
// highest goodness.
Collections.sort(leastBadHalf, new CompareTogetherByGoodness());
return leastBadHalf.get(leastBadHalf.size()-1);
}
Whew! That is a LOT of code for something that would be a few lines in Haskell or Python. Is there a better way to do this?
EDIT:
Addressing some of the answers.
"You don't need to decorate." Well, my fitness computation is very expensive, so I want to compute it once for each note, and save the result for later access as well.
"Store goodness/badness in Note." The goodness or badness is not a property of the note alone; it's only meaningful in context and it can change. So this is a suggestion that I add mutable state which is only meaningful in some contexts, or plain wrong if there's a bug which accidentally mutates it. That's ugly, but maybe a necessary crutch for Java.
Going by what you already have
origList = <something>
decorated = sorted( [(evalFunc(item), item) for item in origList] )
finalList = [item for _, item in decorated]
This is the equivalent in modern Java:
Given your composition object:
Composition composer = ...;
And a list of notes:
List<Note> notes = ...;
Then you can do:
List<Together> notesAllTogetherNow = notes.stream()
.map(note -> new Together(note, composer.evaluate(note)))
.sorted(new CompareTogetherByGoodness())
.collect(Collectors.toList());
To get the best note, you can take a bit further:
Optional<Note> bestNote = notes.stream()
.map(note -> new Together(note, composer.evaluate(note)))
.sorted(new CompareTogetherByBadness())
.limit(notes.size() / 2) // Taking the top half
.sorted(new CompareTogetherByGoodness())
.findFirst() // Assuming the last comparator sorts in descending order
.map(Together::getNote);
You can use streams:
Function<Foo, Bar> func = ...
Comparator<Foo> comparator = ...
var list = ...
var sorted = list.stream()
.sorted(comparator)
.map(func)
.collect(Collectors.toList());
Java plainly includes a Collections.sort :: List -> Comparator -> List that does everything for you. It mutates the original list, though.
Unfortunately, Java's standard library does not include tuples and even a plain Pair; the Apache Commnons library does, though.
In short, you don't need the decorate / undecorate approach in Java.
class Fitness {
double goodness;
double badness;
}
class Together {
Note note;
Fitness fitness;
}
class Note{
}
List<Together> notes = ...
Collections.sort(notes, Comparator.comparingDouble(value -> value.fitness.badness));
List<Together> leastBadHalf = notes.subList(0, notes.size()/2);
return leastBadHalf.stream().max(Comparator.comparingDouble(value -> value.fitness.goodness));
Using the following code, I can set a couple variables to my matches. I want to do the same thing, but populate a map of all instances of these results. I'm struggling and could use help.
val (dice, level) = Regex("""([0-9]*d[0-9]*) at ([0-9]*)""").matchEntire(text)?.destructured!!
This code works for one instance, none of my attempts at matching multiple are working.
Your solution is short and readable. Here are a few options the one you use is largely a matter of preference. You can get a Map directly by using the associate method as follows.
val diceLevels = levelMatches.associate { matched ->
val (diceTwo,levelTwo) = matched.destructured
(levelTwo to diceTwo)
}
Note: This creates an immutable map. If you want a MutableMap, you can use associateTo.
If you want to be concise, you can simplify out the destructuring to local variables and index the groups directly.
val diceLevels = levelMatches.associate {
(it.groupValues[2] to it.groupValues[1])
}
Or, using let, you can also avoid needing to declare levelMatches as a local variable if it isn't used elsewhere --
val diceLevels = Regex("([0-9]+d[0-9]+) at ([0-9]+)")
.findAll(text)
.let { levelMatches ->
levelMatches.associate {
(it.groupValues[2] to it.groupValues[1])
}
}
I realized this was no where near as complicated as I was making it. Here was my solution. Is there something more elegant?
val levelMatches = Regex("([0-9]+d[0-9]+) at ([0-9]+)").findAll(text)
levelMatches.forEach { matched ->
val (diceTwo,levelTwo) = matched.destructured
diceLevels[levelTwo] = diceTwo
}
I have an old question sustained in my mind for a long time. When I was writing code in Spring, there are lots dirty and useless code for DTO, domain objects. For language level, I am hopeless in Java and see some light in Kotlin. Here is my question:
Style 1 It is common for us to write following code (Java, C++, C#, ...)
// annot: AdminPresentation
val override = FieldMetadataOverride()
override.broadleafEnumeration = annot.broadleafEnumeration
override.hideEnumerationIfEmpty = annot.hideEnumerationIfEmpty
override.fieldComponentRenderer = annot.fieldComponentRenderer
Sytle 2 Previous code can be simplified by using T.apply() in Kotlin
override.apply {
broadleafEnumeration = annot.broadleafEnumeration
hideEnumerationIfEmpty = annot.hideEnumerationIfEmpty
fieldComponentRenderer = annot.fieldComponentRenderer
}
Sytle 3 Can such code be even simplified to something like this?
override.copySameNamePropertiesFrom (annot) { // provide property list here
broadleafEnumeration
hideEnumerationIfEmpty
fieldComponentRenderer
}
First Priority Requirments
Provide property name list only one time
The property name is provided as normal code, so as to we can get IDE auto complete feature.
Second Priority Requirements
It's prefer to avoid run-time cost for Style 3. (For example, 'reflection' may be a possible implementation, but it do introduce cost.)
It's prefer to generated code like style1/style2 directly.
Not care
The final syntax of Style 3.
I am a novice for Kotlin language. Is it possible to use Kotlin to define somthing like 'Style 3' ?
It should be pretty simple to write a 5 line helper to do this which even supports copying every matching property or just a selection of properties.
Although it's probably not useful if you're writing Kotlin code and heavily utilising data classes and val (immutable properties). Check it out:
fun <T : Any, R : Any> T.copyPropsFrom(fromObject: R, vararg props: KProperty<*>) {
// only consider mutable properties
val mutableProps = this::class.memberProperties.filterIsInstance<KMutableProperty<*>>()
// if source list is provided use that otherwise use all available properties
val sourceProps = if (props.isEmpty()) fromObject::class.memberProperties else props.toList()
// copy all matching
mutableProps.forEach { targetProp ->
sourceProps.find {
// make sure properties have same name and compatible types
it.name == targetProp.name && targetProp.returnType.isSupertypeOf(it.returnType)
}?.let { matchingProp ->
targetProp.setter.call(this, matchingProp.getter.call(fromObject))
}
}
}
This approach uses reflection, but it uses Kotlin reflection which is very lightweight. I haven't timed anything, but it should run almost at same speed as copying properties by hand.
Now given 2 classes:
data class DataOne(val propA: String, val propB: String)
data class DataTwo(var propA: String = "", var propB: String = "")
You can do the following:
var data2 = DataTwo()
var data1 = DataOne("a", "b")
println("Before")
println(data1)
println(data2)
// this copies all matching properties
data2.copyPropsFrom(data1)
println("After")
println(data1)
println(data2)
data2 = DataTwo()
data1 = DataOne("a", "b")
println("Before")
println(data1)
println(data2)
// this copies only matching properties from the provided list
// with complete refactoring and completion support
data2.copyPropsFrom(data1, DataOne::propA)
println("After")
println(data1)
println(data2)
Output will be:
Before
DataOne(propA=a, propB=b)
DataTwo(propA=, propB=)
After
DataOne(propA=a, propB=b)
DataTwo(propA=a, propB=b)
Before
DataOne(propA=a, propB=b)
DataTwo(propA=, propB=)
After
DataOne(propA=a, propB=b)
DataTwo(propA=a, propB=)
My problem is the following, I have quite a long Getter, i.e.,
objectA.getObjectB().getObjectC().getObjectD().getObjectE().getName();
Due to "bad" database/entity design (some things were introduced later than others) it happens that getObjectB(), getObjectC() or getObjectD() could return NULL.
Usually we use null-checks all the time, but in this case, I'd have to use
ObjectB b = objectA.getObjectB();
if (b != null) {
ObjectC c = b.getObjectC();
if (c != null) {
ObjectD d = c.getObjectD();
if (d != null)
return d.getObjectE().getName();
}
}
return "";
Instead it would be much easier to simply use a try-catch block
try {
return objectA.getObjectB().getObjectC().getObjectD().getObjectE().getName();
} catch (NullPointerException e) {
return "";
}
In this case I don't really care which object returned NULL, it's either display a name or don't. Are there any complications or is it bad design to use try-catch instead of checks?
Thanks for your input.
If it is an option to use Java 8, you can use Optional as follows:
Optional.ofNullable(objectA)
.map(a -> a.getObjectB())
.map(b -> b.getObjectC())
.map(c -> c.getObjectD())
.map(d -> d.getObjectE())
.map(e -> e.getName())
.orElse("");
This kind of method chaining is called a "Train wreck" and is not preferred.
Such a statement also violates the Law of Demeter . Let me give you an example from the book Clean code by Robert C Martin:
String scratchDirPath = ctxt.getOptions().getScratchDir().getAbsolutePath();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(scratchDirPath));
//write to file...
This is similar to what you have and it is a bad practice. This could atleast be refactored to below:
Options options = ctxt.getOptions();
File scratchDir = options.getScratchDir();
String scratchDirPath = scratchDir.getAbsolutePath();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(scratchDirPath));
//write to file...
This is still violating the Law of Demeter but is at least partially better.
The most preferable way would be to find out why the scratchDirPath is needed and ask ctxt object to provide it to you. So it would look like -
BufferedOutputStream bos = ctxt.createScratchDirFileStream();
This way ctxt does not expose all its internals. This decouples the calling code from the implementation of ctxt.
It's really a judgement call only you and your team can make, but there's (at least) one objective thing I'll call out: In the case where one of those methods returns null, your first code block will perform better than your second one. Throwing an exception is expensive relative to a simple branch. (In the case where none of the methods returns null, I think the second might be almost unmeasurably faster than the second as you avoid the branching.) In either case, if performance matters, test it in your environment. (But test it properly; micro benchmarks are hard. Use tools.)
Most of time, the difference won't matter in the real world, of course, but that's the significant difference at runtime.
I try to understand the new Java 8 Streams and I tried for days to transfer nested foreach loops over collection in Java 8 Streams.
Is it possible to refactor the following nested foreach loops including the if-conditions in Java-8-Streams?
If yes what would it look like.
ArrayList<ClassInq> Inq = new ArrayList<>();
TreeMap<String, SalesQuot> Quotations = new TreeMap<>();
ArrayList<ClassInq> tempInqAndQuot = new ArrayList<>();
ArrayList<SalesQuot> tempQuotPos = new ArrayList<>();
for(ClassInq simInq : this.Inq) {
if(!simInq.isClosed() && !simInq.isDenied()) {
for(Map.Entry<String, SalesQuot> Quot: Quotations.entrySet()) {
SalesQuot sapQuot = Quot.getValue();
if(sapQuot.getInquiryDocumentNumber().compareTo(simInq.getSapInquiryNumber()) == 0) {
simInq.setSAPQuotationNumber(sapQuot.getQuotationDocumentNumber());
tempInqAndQuot.add(simInq);
for(Map.Entry<String, SalesQuotPosition> quotp : sapQuot.getPosition().entrySet()) {
tempQuotPos.add(quotp.getValue());
}
}
}
}
}
Thanks a lot for your help.
BR
First, try to adhere to the Java naming conventions, as your upper case variable names make it really hard to read your code. Second, it’s a good thing that you want to learn about Stream API but you should not ignore the basics of the pre-Java 8 Collection APIs.
It’s not useful to iterate over an entrySet() when you are only interested in either, keys or values. You do it two times within a small piece of code.
At the first appearance you can replace
for (Map.Entry<String, SalesQuot> Quot: Quotations.entrySet()){
SalesQuot sapQuot = Quot.getValue();
with the simpler
for (SalesQuot sapQuot: Quotations.values()){
At the second, the entire
for(Map.Entry<String,SalesQuotPosition> quotp: sapQuot.getPosition().entrySet()){
tempQuotPos.add(quotp.getValue());
}
can be replaced by
tempQuotPos.addAll(sapQuot.getPosition().values());
Thus even without streams, your code can be simplified to
for (ClassInq simInq : this.Inq){
if (!simInq.isClosed() && !simInq.isDenied()){
for (SalesQuot sapQuot: Quotations.values()){
if (sapQuot.getInquiryDocumentNumber().compareTo(simInq.getSapInquiryNumber()) == 0){
simInq.setSAPQuotationNumber(sapQuot.getQuotationDocumentNumber());
tempInqAndQuot.add(simInq);
tempQuotPos.addAll(sapQuot.getPosition().values());
}
}
}
}
though it’s still not clear what it is supposed to do and whether it’s correct. Besides the errors and suspicions named in the comments to your question, modifying the incoming values (esp. from the outer loop) does not look right.
It’s also not clear why you are using ….compareTo(…)==0 rather than equals.
However, it can be straight-forwardly rewritten to use streams without changing any of the code’s logic:
this.Inq.stream().filter(simInq -> !simInq.isClosed() && !simInq.isDenied())
.forEach(simInq -> Quotations.values().stream().filter(sapQuot ->
sapQuot.getInquiryDocumentNumber().compareTo(simInq.getSapInquiryNumber())==0)
.forEach(sapQuot -> {
simInq.setSAPQuotationNumber(sapQuot.getQuotationDocumentNumber());
tempInqAndQuot.add(simInq);
tempQuotPos.addAll(sapQuot.getPosition().values());
})
);
Still, I recommend cleaning up the original logic first before rewriting it for using other APIs. The stream form would greatly benefit from a more precise definition of what to achieve.