Jason Bullers

Ranch Hand
+ Follow
since Dec 27, 2011
Merit badge: grant badges
For More
Cows and Likes
Cows
Total received
In last 30 days
0
Forums and Threads

Recent posts by Jason Bullers

Thanks for the cows

Salvin: I guess you're wondering what I would use in the Stream API to implement this?

I'd prefer IntStream to avoid unnecessary boxing and unboxing of ints and probably use the specialized min method instead of the more general reduce. The only other choice is what to do about the case of an empty Stream. That depends on usage: a "marker" like -1 may be sufficient for a method that's an implementation detail, but if it's part of a public API, I'd prefer to just send the Optional back to the caller and let them handle it as they like. So I'd do something like:
I'm not sure where to start, since "I literally understood nothing" is quite vague, but totally understandable. I agree with Campbell's assessment on the tutorial: it does seem to go much into the motivation (why you should care about any of the points listed), instead assuming that you already kind of know what Functional Programming is all about. I'll try and walk through the first of those three articles and rephrase to try and shed some more light on the subject. If you have more specific questions though, that would be really helpful for us to understand what you're feeling unsure about and better target our answers.

I'm going to stay away from the examples given in the article. They seem a little weird to me, and at least the first one is not quite the right way to use the Stream API. Instead, I'll try and stick to concepts and only show (sort of) the Java APIs once the concepts have been introduced.

The three main points listed by the article really fall under two important ideas: functions are first class, and so can be passed around, even to other functions; and functions should be "pure", depending only on their inputs to generate their outputs. Together, these two ideas form a programming paradigm where the function is king and mutation is limited. This is where all the hype comes from: modern development likely needs to take advantage of multiple cores, which means a certain degree of parallel processing. Functions that don't mutate and have predictable outputs based on their inputs are much easier to reason about (and debug!) than objects and methods that have mutable internal state.

I'll try to showcase how functional programming can help make it easier to reason about a problem with a (hopefully not too) simple example: we have a list of people's ages and we want to calculate the youngest adult age (>= 18).

Starting with a more imperative approach, we might try something like:

There are a few interesting things going on here. First, youngestAdultAge is (potentially) assigned to multiple times. Here we don't really have a problem, aside from the potential for mistakenly reassigning the variable, but imagine if we had a huge number of ages to process: it wouldn't be obvious how we might go about parallelizing this implementation without the multiple threads clobbering each other by writing to the same variable. Second, the logic is a little spread out (capturing the youngest age is spread over the declaration, half of the if and the assignment). And third, we'd have to copy/paste the whole function with a few changes if we wanted to find, for example, the oldest child.

So let's consider what we might need here if we want to instead approach the problem in a more functional way. First, let's write some functions: one to determine if a given age was >= 18, and another to determine the minimum of a two ages:

The first function is what we would call a Predicate: it's a function that, given some input, makes a decision about that input and returns either true or false. There really isn't any difference between a "predicate" and a "function"; a predicate is just a function that returns a Boolean. Typically, predicates are used to select elements out of a sequence (i.e. decide which elements should be processed and which should be ignored).

This is where the notion of "higher-order" functions (functions that take functions) comes in: imagine that our sequence of ages has some method on it, let's call it filter, that takes a Predicate and applies it to each element of the sequence. Selecting all the adult ages would then look something like (I'm assuming you're familiar with lambda syntax):

So now we have all the adult ages, we want to find the youngest (minimum). We have our function for that, but how would we use it? What we'd like to do is take that filtered sequence of ages and reduce it to a single value: the youngest age. Image that our sequence of ages has another method on it, let's call it reduce, that takes a function to apply over and over to the sequence of ages until the result is a single value. Finding the youngest adult would then look something like:

The reduction may require a little more explanation than the filter. I've called the two arguments to the function youngest and age because the first is there to track the youngest age in the same way as the youngestAdultAge in the imperative solution, and the second is the age we are currently comparing against the youngest. To visualize what's going on, consider this sequence of ages: [32, 22, 40]. The reduction does the following:

For completeness, we'll use a two-argument variant of reduce that takes an identity as its first argument. This is an identity in the mathematical sense: including it in the reduction should not cause any change to the calculation. For addition, the identity is 0; for multiplication, the identity is 1; for our current example, we've already seen the identity in the imperative implementation: Integer.MAX_VALUE. Here are the two implementations together for comparison:

You can see here that the functional implementation is much closer to the problem statement than the imperative one. Also, because it takes advantage of higher-order functions, it's trivial to change what we're looking for. Going with the earlier example of oldest child, we would just have to change what we plug in:

I hope that helps!
The garbage collector calls that method when the object is being cleaned up. If I remember right, there isn't any guarantee when (or if) it will be called, or even how many times it could be called.

It's all really fiddly and relying on it for cleaning up an object is generally a pretty bad idea. Prefer explicit methods for that. I'm happy to see it finally deprecated!

I actually had a really weird bug at work related to this hook a few weeks back that took quite a while to track down. What was happening was I had these "connection" objects that are identified by a key (name), and seemingly at random, a connection would stop reading data. It turns out what was happening is that the object's clean up code was being executed through the finalize hook and acted by removing itself by name from a really important singleton that managed polling over registered connections. The problem was that, since I was closing and reopening the connection (important to the logic of the application), the new objects were getting removed from that singleton whenever the garbage collector decided to clean up the old references and the finalize method got called.

Granted, using finalize here was likely a bad design decision, or else the implementation was just not quite safe. Either way, I'm sure mine isn't the only software with "bad" implementations like that.
7 years ago
Oooo I want to play.

So, assuming that the operation you take in the loop is some sort of aggregation, then effectively we want to implement a short-circuiting reduction on the stream. And since the problem statement allows for dirty hacks, we can have fun with code that should never see the light of day.

Imagine our aim was to calculate the product of a stream of integers:

Here we're processing three more numbers than we needed to, and would like to terminate early when we encounter that 0. Clojure actually has a pretty cool function for that called reduced that "forces" the reduction to terminate with the value supplied to that function. What if we tried something similar here with some ugly trickery?
7 years ago
Well, for starters, you aren't following the instructions about what constructors to write:

Carolin Sha wrote:
1. a constructor that takes 3 parameters. Use the super keyword
2. a constructor that only takes 2 parameters, that is it does not have a pricePerKilo parameter. use the keyword this, and set the value of pricePerKilo to -1



Your answer is right there in the error message as well:


required: String,String
found: no arguments
reason: actual and formal argument lists differ in length



Look at the constructor that is provided in the Grocery class, and then look at the constructor you are invoking with super(). Note that super() is invoking a constructor and takes arguments just the same way a constructor does.
9 years ago
Ack, how did I miss that! Still, that implies that the call to getName() should be generating the NPE, so I'm not completely nuts.
9 years ago
What is the output that you are getting? If what you show as originalList is what you are in fact using as your input, then that might be part of your problem. That's a Groovy map, and you keep repeating the same keys. Try printing it out. You'll see it only contains the last entry:



What you probably want there is a list of maps:

9 years ago
That book should still be good enough to teach you the basics of Java. The changes in Java 6 will not have much (if any) impact on the way you write Java code. Java 7 will have only minor, mostly cosmetic impact with features such as the diamond operator (List<String> = new ArrayList<>();), multi-catch (catch (MyException1 | MyException 2 e) { ... }), underscores in numbers (int reallyBigNumber = 1_000_000_000;), etc.

Java 8, on the other hand, represents the largest change to the Java language since Java 5 (arguably an even bigger change since it brings with it a bit of a paradigm shift). That said, you should still be okay learning Java with your book, but be prepared to find additional material that covers Java 8 and everything new that has come with it (especially lambdas, the streams API, and default methods in interfaces).
9 years ago
Hmm... are you sure the exception is on the call to setName(String)? Looking at the code, that doesn't make much sense to me. Your setName(String) method only performs an assignment, so it wouldn't matter if its argument (name) was null. The only other thing that could be null on that line is array(i), but if that was null, then the getName() call would have failed with an NPE.

What does seem possible is that getName() fails with an NPE, since internally it calls toUpperCase() on the name field before returning it.

Disclaimer: I haven't tried running the code yet, just read through it.
9 years ago

Jordan King wrote:Well I can't really see the main method calculating pay but perhaps I could create a method that takes pay and hours from my constructor and calculates it. I have the program working and ready to turn in, I'm just wondering what would help me more in the long run, using the main method or creating a separate method.


Generally you want your main method to be as light as possible. It's just the launching point of your application and should not really include any kind of logic. You could try creating a method that uses your people objects and figures out the pay given the people. Try and out and post it here!

Jordan King wrote:Also if it is appropriate to put each separate person [constructor] (a,b,c) into the main method. perhaps I am overthinking it at this stage?


Not sure what you mean by this. Can you show an example?
9 years ago

Junilu Lacar wrote:
Yeah, about giving examples, I like your helpfulness but consider what I said about letting them do their work and providing too much detail. It's fine to do that when they have shown some effort but I think it's a little premature and could skirt the border on aiding and abetting.



Very good point. Know thy audience and all that Looking at it again, I agree that I did provide more detail than I should have for this situation.

Junilu Lacar wrote:
Not really sure I understand where you're heading with the magic numbers... are you thinking perhaps of an error code or status code of some kind? Again, let's take that somewhere other than Beginning Java or at least wait until OP asks about it. Otherwise, we're running the risk of digressing and confusing OP. Or is it too late to think about that now?



Exactly. If you separate concerns properly, then you'd need to return something to indicate status. This is a point where I'm on the fence still. I definitely see your point about moving too quickly, but I am also worried about breeding bad habits. Separation of concerns is very important, and to brush it off in a "toy program," especially where it is obviously being violated, makes me feel uneasy. I'd rather drive home that point before a beginner gets comfortable with a particular (wrong) style.

Let's try and put the lid back on this box, though. Jordan: ignore most of my rambling (for now at least) Take a look at the Google search Junilu linked to earlier and play around with printing values out (I think one of the tutorials there also talks about formatted strings). Figuring out how to deal with output properly is a good first step that will help you write more complicated programs (so you can see the results of those programs).
9 years ago

Junilu Lacar wrote:
Invalid data does not necessarily warrant a RuntimeException to be thrown, especially not with exception messages like "Worked too many hours" and "Does not meet minimum wage requirements" -- those are more along the lines of what are called "business rules". If you were to check for and say that "negative numbers are not allowed for payment calculations" that would be more in line with a condition where an IllegalArgument exception is warranted.

In this program, it would probably be more appropriate to make checks with if statements, as Jordan did, to see whether the data fell within the "business rules" enforced by the program, then display the appropriate messages if it didn't.



That's a fair point, though I disagree on displaying messages as was done in the original. A method should do only one thing. Calculating pay and printing to the console are two things. You also should not allow for the construction of an object that is in an invalid state.

All that considered, one possibility is that the constructor in my example should take just a name, and the calculation takes both time worked and pay rate. This seems a bit odd to me, though.

If you want to avoid RuntimeExceptions, then calculate pay might throw checked exceptions that properly line up with the domain (one for working too many hours and one for not being paid enough). The client programmer would then be forced to handle that situation where pay could not be calculated because the arguments were invalid with respect to the business rules.

If you want to avoid exceptions entirely, then a double return type is insufficient: the only way you could communicate that the calculation was not performed would be through magic numbers being returned, and that's pretty awful. You'd need some sort of tri-state return to cover the three cases: worked too much, paid too little, and the calculation for pay worked.
9 years ago
First you'll need to give each Person a name to start with. I'd also suggest restructuring your class to remove those print statements and provide an appropriate method to calculate pay. Here's something to start with:



Whether or not you should be throwing exceptions like that or just calculate things anyway is another discussion, but IMO it beats silently doing nothing and printing to the console.
9 years ago
The line that prints the final pay is in the else block. Person b has a pay greater than 8, so only that else if will be executed. If you want the final pay to be printed no matter what, you'll have to move it outside the if-else blocks.
9 years ago

Winston Gutkowski wrote:
Better still, write Problem and Performance classes and put them in there. Indeed, you might even be able to use those classes to break up that nasty logic too.

Good programming (after getting things correct of course) is mostly about writing readable code; and the surest way to get your programs consigned to File 13 is to write ones that nobody understands.



This. I started looking at it and thinking about using an enum and putting the behaviour there, but then quickly realized that this method is doing way too much. There's four arguments and from what I can tell, they seem to be fairly disjoint. Conceptually, there doesn't seem to be much of a connection between the start date, the count, and the number of problems. There even seem to be (maybe) two different sets of enums in those strings that get returned.

I'd definitely take a step back and figure out what this method is trying to do. Explain it in plain English, looking for the word "and" in your explanation. That's a good indicator that you have more than one concept that should be split up.
9 years ago