KotlinCS 124 LogoJava
PrevIndexNext
Kotlin
Java
  • Implementing a Map : 04/26/2024

  • Streams : 04/25/2024

  • Generics : 04/24/2024

  • Hashing : 04/23/2024

  • Binary Search : 04/22/2024

  • MP3: Course Ratings : 04/19/2024

  • Quicksort : 04/18/2024

  • Merge Sort : 04/17/2024

  • Sorting Algorithms : 04/16/2024

  • MP Debugging Part 1 : 04/15/2024

  • MP2: Course Activity : 04/12/2024

  • Practice with Recursion : 04/11/2024

  • MP Debugging Part 0 : 04/10/2024

  • MP2: API Client : 04/09/2024

  • MP2: API Server : 04/08/2024

  • Trees and Recursion : 04/05/2024

  • Trees : 04/04/2024

  • Recursion : 04/03/2024

  • MP1: Filtering and Search : 04/02/2024

  • MP1: Loading and Sorting : 04/01/2024

  • Lists Review and Performance : 03/29/2024

  • Linked Lists : 03/28/2024

  • Algorithms and Lists : 03/27/2024

  • Continuing MP0 : 03/26/2024

  • Getting Started with MP0 : 03/25/2024

  • Lambda Expressions : 03/22/2024

  • Anonymous Classes : 03/21/2024

  • Practice with Interfaces : 03/20/2024

  • Implementing Interfaces : 03/19/2024

  • Using Interfaces : 03/18/2024

  • Working with Exceptions : 03/08/2024

  • Throwing Exceptions : 03/07/2024

  • Catching Exceptions : 03/06/2024

  • References and Polymorphism : 03/05/2024

  • References : 03/04/2024

  • Data Modeling 2 : 03/01/2024

  • Equality and Object Copying : 02/29/2024

  • Polymorphism : 02/28/2024

  • Inheritance : 02/27/2024

  • Data Modeling 1 : 02/26/2024

  • Static : 02/23/2024

  • Encapsulation : 02/22/2024

  • Constructors : 02/21/2024

  • Objects, Continued : 02/20/2024

  • Introduction to Objects : 02/19/2024

  • Compilation and Type Inference : 02/16/2024

  • Practice with Collections : 02/15/2024

  • Maps and Sets : 02/14/2024

  • Lists and Type Parameters : 02/13/2024

  • Imports and Libraries : 02/12/2024

  • Multidimensional Arrays : 02/09/2024

  • Practice with Strings : 02/08/2024

  • null : 02/07/2024

  • Algorithms and Strings : 02/06/2024

  • Strings : 02/05/2024

  • Functions and Algorithms : 02/02/2024

  • Practice with Functions : 02/01/2024

  • More About Functions : 01/31/2024

  • Errors and Debugging : 01/30/2024

  • Functions : 01/29/2024

  • Practice with Loops and Algorithms : 01/26/2024

  • Algorithms : 01/25/2024

  • Loops : 01/24/2024

  • Arrays : 01/23/2024

  • Compound Conditionals : 01/22/2024

  • Conditional Expressions and Statements : 01/19/2024

  • Operations on Variables : 01/18/2024

  • Variables and Types : 01/17/2024

  • Welcome to CS 124 : 01/16/2024

Functions

boolean searchArray(int[] values, int lookingFor) {
for (int i = 0; i < values.length; i++) {
if (values[i] == lookingFor) {
return true;
}
}
return false;
}
int[] example = {1, 2, 5};
System.out.println(searchArray(example, 2));
System.out.println(searchArray(example, 4));

Next we’ll learn how to package up our code into reusable pieces called functions.

Along with implementing new algorithms and exploring new data structures, we’ll also explore new ways of structuring our programs in future lessons. Functions—also called methods or subroutines—are the basic structural building blocks of computer programs.

Important note: we’re charging forward in our exploration of Java. Functions are such an important idea that it’s worth getting a bit ahead of ourselves. Starting tomorrow we’re going to slow down, practice what we’ve already learned, and integrate. Put another way: tomorrow’s lesson is shorter!

Why Functions?
Why Functions?

Let’s return to the search algorithm that we presented in the last lesson:

int[] values = {1, 2, 5};
int lookingFor = 4;
for (int i = 0; i < values.length; i++) {
if (values[i] == lookingFor) {
System.out.println("Found!");
break;
}
}

This is a nice example of solving one specific problem: search for the value contained in lookingFor in the array values. But what if I wanted to also look for another value in a second array? I could do this:

int[] values = {1, 2, 5};
int lookingFor = 4;
for (int i = 0; i < values.length; i++) {
if (values[i] == lookingFor) {
System.out.println("Found!");
break;
}
}

This works fine. But there’s a problem: we have duplicated our algorithm now in two places! We could do this, and continue copy-and-pasting our search algorithm wherever we needed it in our code. But a better strategy is to refactor our code so that we can reuse the algorithm in multiple places.

Functions
Functions

Just like we did with algorithm, let’s carefully parse the Wikipedia definition of function:

In computer programming, a subroutine is a sequence of program instructions that performs a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed.

Now let’s consider how to convert the code for our search algorithm into a function.

int[] values = {1, 2, 5};
int lookingFor = 4;
for (int i = 0; i < values.length; i++) {
if (values[i] == lookingFor) {
System.out.println("Found!");
}
}

To make this code reusable, our goal is to rewrite it so that it can look for any int value in any array of ints. To do this, we need to separate the algorithm that can be reused from the inputs that can vary. Let’s walk through how to do that:

int[] values = {1, 2, 5};
int lookingFor = 4;
for (int i = 0; i < values.length; i++) {
if (values[i] == lookingFor) {
System.out.println("Found!");
}
}

Anatomy of a Function
Anatomy of a Function

The walkthrough above identified two of the required parts of a function. First, we need the code that we’re going to reuse. Second, we need to identify the data or inputs that are provided to that code.

There are two additional requirements. Third, each function needs a name so that we can identify it when it is reused. Fourth, functions need some way of returning a result—in our example, whether or not the value was found or not.

These set of requirements lead us to our first function definition. Let’s go through each part of it carefully together:

boolean searchArray(int[] values, int lookingFor) {
for (int i = 0; i < values.length; i++) {
if (values[i] == lookingFor) {
return true;
}
}
return false;
}

Calling Functions
Calling Functions

We call executing the reusable logic that a function encapsulates calling that function. To call a function, we need to identify it using its name and provide the inputs that it needs to complete the task. Let’s go through calling our search function and several different ways that we can use the result:

boolean searchArray(int[] values, int lookingFor) {
for (int i = 0; i < values.length; i++) {
if (values[i] == lookingFor) {
return true;
}
}
return false;
}

Function Arguments
Function Arguments

Part of how we make functions reusable is by having them accept arguments. For example, this function does implement a search, but it’s not particularly useful:

boolean searchArrayForFour(int[] values) {
for (int i = 0; i < values.length; i++) {
if (values[i] == 4) {
return true;
}
}
return false;
}

In this case searchArrayForFour is a perfectly valid algorithm for search an array, but only for the value 4. What if we want to search for 5, or 8? We don’t want to have to write a separate search function for each value we might want to look for!

Instead, as we see above, we let the value that we are looking for be a parameter that is provided to the function by the caller. This allows us to search for any value, not just a specific value. In the walkthrough below we talk a bit more about function arguments and compare them to the variable declaration and initialization we’ve seen previously.

boolean searchArray(int[] values, int lookingFor) {
for (int i = 0; i < values.length; i++) {
if (values[i] == lookingFor) {
return true;
}
}
return false;
}

return and Return Type
return and Return Type

Our new bit of Java syntax in this lesson is the return statement. return causes a function to immediately stop and return or yield a value:

int subtractOne(int value) {
return value - 1;
}
System.out.println(subtractOne(3));
double divideByTwo(double input) {
return input / 2.0;
}
double smaller = divideByTwo(7.0);
System.out.println(smaller);

The return value must match the return type of the method, which is part of the method declaration. And every function must return a value of the type declared. For example, this doesn’t work:

boolean isPositive(int value) {
if (int > 0) {
return true;
} else if (int < 0) {
return false;
}
}

Practice: Add One Function

Created By: Geoffrey Challen
/ Version: 2020.8.0

For this homework you'll write a simple function, a reusable piece of code that allows us to build more complex computer programs.

We're going to start simple. Declare and implement a function called addOne. Your function should accept a single int argument and return the result of adding one to its argument.

return Is Not System.out.println
return Is Not System.out.println

We’ll continue using System.out.println to trace the execution of our programs as they run. But it’s important to note that this is not returning a value:

double divideByTwo(double input) {
System.out.println(input); // I haven't returned anything yet...
return input / 2.0;
}
double value = 2.0;
System.out.println(value);
value = divideByTwo(value);
System.out.println(value);

Practice: Game Tiebreaker Function

Created By: Geoffrey Challen
/ Version: 2021.8.0

Two players have completed a game. Write a method (or function) named whoWon to determine the winner!

whoWon receives three parameters in the following order: the score of the first player as an int, the score of the second player as an int, and whether the first player played first as a boolean.

If either player scored more points than the other, they are the winner! However, if both players tie, then the player that played second is the winner.

Return the result of the game as an int. You should return 1 if Player 1 won and 2 if Player 2 won.

If you have solved this problem previously without writing a method, you may reuse your old code! However, you may try to eliminate the winner variable that we used previously.

Homework: Number Sum Game Function

Created By: Geoffrey Challen
/ Version: 2022.8.0

Your friend invented a new game and wants your help to create the computer implementation. Of course, you're happy to help!

Here's how the game works. A set of cards with positive values are placed face down on a table. The player is allowed to turn over some number, but not all. They then guess the sum of all the cards. At that point, all the values are revealed. The players score is equal to how far off their guess was—the distance between their guess and the actual sum. (Lower is better.)

As an example, if the values were 1, 2, and 4, and the guess was 7, the score would be 0—a perfect score! However, if the values were 1, 2, and 8, and the guess was 7, the score would be 4. And if the the values were 2, 2, and 5, and the guess was 124, the score would be 115.

Write a method (or function) named scoreGame that returns the score of a game. scoreGame receives two parameters: an int[] containing the values on the cards, and an int that stores the player's guess. Your method should return the score of the game as an int.

You will need to compute the sum of the values in the array! You may also find the Math.abs method helpful when completing this problem, but it is not required.

If you have solved this problem previously without writing a method, you may reuse your old code! However, you may try to eliminate the score variable that we used previously.

More Practice

Need more practice? Head over to the practice page.