String notSecret = "VUdBIGlzIGJldHRlciB0aGFuIEdBIFRlY2g="; String decoded = new String(java.util.Base64.getDecoder().decode(notSecret)); System.out.println(decoded);-- Proven Fact
This class exercise explores functional interfaces and lambda expressions in conjunction with generic methods and interfaces. In this exercise, only the generic method signatures will be provided. Implementation details are left to the student.
- LO2.d: (Partial) Implement new generic methods, interfaces, and classes in a software solution.
- LO2.e: (Partial) Utilize existing generic methods, interfaces, and classes in a software solution.
- LO4.a: (Partial) Design, create and use interfaces in a software solution.
- LO4.b: (Partial) Utilize interface-based polymorphism in a software solution.
- The Java™ Tutorials: Generic Methods
- The Java™ Tutorials: Lambda Expressions
java.util.function.Predicate
Interface Documentationjava.util.function.Function
Interface Documentation
In your notes, clearly answer the following questions. These instructions assume that you are logged into the Odin server.
NOTE: If a step requires you to enter in a command, please provide in your notes the full command that you typed to make the related action happen. If context is necessary (e.g., the command depends on your present working directory), then please note that context as well.
-
Use Git to clone the repository for this exercise onto Odin into a subdirectory called
cs1302-ce17
:$ git clone --depth 1 https://github.com/cs1302uga/cs1302-ce17.git
-
Change into the
cs1302-ce17
directory that was just created and look around. There should be multiple Java files contained within the directory structure. To see a listing of all of the files under thesrc
subdirectory, use thefind
command as follows:$ find src
-
NOTE: In this exercise, you will be referring to multiple generic interfaces, some of which have two generic type parameters. It's very important that you keep keep parameter composition in mind when referring to the API documentation. For example, consider the following code snippets that illustrate type parameter composition:
public interface SomeInterface<A> { A foo(); } // SomeInterface
public static <T> void bar(SomeInterface<T> si) { T var = si.foo(); // foo returns T, because A is replaced with T } // bar
-
LambdaFun.java
contains method signatures and documentation for three generic methods. We will implement and test these methods in the order that they appear in the Java program, starting withprintlnMatches
. The exact signature for this method is:private static <T> void printlnMatches(T[] t, Predicate<T> p)
Answer the following questions about this method in your notes:
- What is the generic type parameter?
- Specifically, what reference types can replace
T
? - In order to call this method, we need a reference to an object of a class that implements
Predicate<T>
.Predicate<T>
is a functional interface. Write the full method signature of the single, abstract method of this class in your notes. Pay careful attention to the return type and the type of the formal parameter.
-
Implement the
printlnMatches
method inLambdaFun.java
. You do not need to use a lambda for this step. You will only need to use the object of typePredicate<T>
referred to byp
to call the appropriate method. If you did the previous step, then you know what method(s) can be called withp
. Implement thisprintlnMatches
method using some code that, usesp
. -
At the end of the
main
method ofLambdaFun
class:- Declare a variable of type
Predicate<String>
. - Initialize the variable using a lambda expression which provides an implementation for the single, abstract
method of the
Predicate<String>
interface. See the Oracle tutorial if you're still unsure about the syntax. Use your answer for 1.iii. to help you write this lambda. - This lambda should return
true
if the string argument contains the letter"a"
(case sensitive). You may wish to refer to the documentation forjava.lang.String
, provided here.
- Declare a variable of type
-
Variable
p
now references an object of typePredicate<String>
. HOLD THE FRONT DOOR! That one line of code created a class that implemented an interface and created an object of that class! It must be the case sincep
is a reference variable of an interface type and the code compiles. This object contains a specific implementation of the single abstract method in the interface. -
Call
printlnMatches
by passing in arraymyStrings
along with your newly createdPredicate<String>
variable. -
Compile and run your code. You will know if everything is working correctly if the method only prints strings containing the letter
"a"
. -
Stage and commit all changes.
-
Create three additional
Predicate<String>
objects to further test yourprintlnMatches
method on the same array. Try to make them interesting! Make sure to provide sufficient output so that it will be easy to convince your TA or instructor that everything is working properly. -
Make sure your code passes
checkstyle
then stage and commit all changes.
-
Take a close look at the
printlnMappedMatches
method and its associated Javadoc inLambdaFun.java
. The exact signature for this method is:private static <T> void printlnMappedMatches(T[] t, Predicate<T> p, Function<T, String> f)
Answer the following questions about this method in your notes:
- What is the generic type parameter?
- Specifically, what reference types can replace
T
? - In order to call this method, we need a reference to an object of a class that implements
Function<T, String>
and a reference to an object of a class that implementsPredicate<T>
. Similar toPredicate<T>
,Function<T, R>
is a functional interface. Write the full method signature of the single, abstract method ofFunction<T, R>
in your notes. Pay careful attention to the return type and the type of the formal parameter. Note: The method can (but doesn't have to) return a datatype that is different from the datatype of the parameter.
-
Implement the
printlnMappedMatches
method inLambdaFun.java
. You do not need to use a lambda for this step. You will only need to use theFunction<T, R>
andPredicate<T>
references to call the appropriate methods. -
At the end of the
main
method ofLambdaFun
class:- Declare a variable of type
Predicate<Email>
and assign to it, using a lambda expression, a referene to an object that tests if the sender of the email does not have a"gatech.edu"
email address (we'll "pretend" that they go to the spam filter). Remember, you can always refer to the API documentation for the associated interface when trying to determine the layout of your lambda. - Declare a variable of type
Function<Email, String>
and assign to it, using a lambda expression, a reference to an object that takes anEmail
object as a parameter and return the contents of the email as some nicely formattedString
. Remember, you can always refer to the API documentation for the associated interface when trying to determine the layout of your lambda.
- Declare a variable of type
-
Call the
printlnMappedMatches
using your newly created variables to filter out emails in the array referred to byinbox
from our rival school. Make sure to provide sufficient output so that it will be easy to convince your TA or instructor that everything is working properly. -
Stage and commit all changes.
-
Create two additional
Function<Email, String>
objects to further test yourprintlnMappedMatches
method on the same array with the same predicate. In other words, you can provide different ways to print out the emails. Make sure to provide sufficient output so that it will be easy to convince your TA or instructor that everything is working properly. -
Make sure your code passes
checkstyle
then stage and commit all changes.
Each student needs to individually submit their own work.
-
Create a plain text file called
SUBMISSION.md
directly inside thecs1302-ce17
directory with the following information.- Your name and UGA ID number;
- Collaborator names, if any; and
- If you created the API website, include the full link to the site you generated.
Here is an example of the contents of
SUBMISSION.md
.1. Sally Smith (811-000-999) 2. Collaborators: Joe Allen, Stacie Mack 3. https://webwork.cs.uga.edu/~user/cs1302-ce17-doc
-
Change directories to the parent of
cs1302-ce17
(e.g.,cd ..
fromcs1302-ce17
). If you would like to make a backup tar file, the instructions are in the submissions steps for ce02. We won't repeat those steps here and you can view them as optional. -
Use the
submit
command to submit this exercise tocsci-1302
:$ submit cs1302-ce17 csci-1302
Read the output of the submit command very carefully. If there is an error while submitting, then it will displayed in that output. Additionally, if successful, the submit command creates a new receipt file in the directory you submitted. The receipt file begins with rec and contains a detailed list of all files that were successfully submitted. Look through the contents of the rec file and always remember to keep that file in case there is an issue with your submission.
Note: You must be on Odin to submit.
Copyright © Michael E. Cotterell, Bradley J. Barnes, and the University of Georgia. This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License to students and the public and licensed under a Creative Commons Attribution-NonCommercial 4.0 International License to instructors at institutions of higher education. The content and opinions expressed on this Web page do not necessarily reflect the views of nor are they endorsed by the University of Georgia or the University System of Georgia.