Java Lambda Expressions - JDK 8 |
|
Outline
|
References:
|
jbr.addActionListener (e -> readFile());
jbd.addActionListener (e -> displayCave ());
jbs.addActionListener (e -> search ((String)(jcb.getSelectedItem()), jtf.getText()));
// jbr.addActionListener ( new ActionListener () {
// public void actionPerformed (ActionEvent e) {
// readFile ();
// } // end required method
// } // end local definition of inner class
// ); // the anonymous inner class
//
// jbd.addActionListener ( new ActionListener () {
// public void actionPerformed (ActionEvent e) {
// displayCave ();
// } // end required method
// } // end local definition of inner class
// ); // the anonymous inner class
//
// jbs.addActionListener ( new ActionListener () {
// public void actionPerformed (ActionEvent e) {
// search ((String)(jcb.getSelectedItem()), jtf.getText());
// } // end required method
// } // end local definition of inner class
// ); // the anonymous inner class
// File: LambdaExampleND.java
// Date: Sep 13, 2015
// Author: Nicholas Duchon
// Purpose: show how to consume a lambda expression
// Note: Motivated by an example by
// Patrick Smith, CMSC 335, Fall, 2015
import java.util.function.Consumer;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JTextField;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
class ButtonND extends JButton {
public static final long serialVersionUID = 94385798;
public ButtonND (String n, Consumer<ActionEvent> ae ) {
super (n);
addActionListener(
e -> ae.accept (e) );
} // end constructor
} // end class ButtonND
public class LambdaExampleND extends JFrame {
public static final long serialVersionUID = 3498;
JTextField jtf = new JTextField ();
public LambdaExampleND () {
super("LambdaExampleND");
String [] options = {
"a", "b", "c", "d", "e", "f"
, "g", "h", "i", "j", "k", "l"
, "m", "n", "o"
, "Camel", "Dog", "Peacock"
}; // end String options
JPanel jp = new JPanel();
for (String s: options)
jp.add (
new ButtonND (s, e -> clickN (s)) );
jp.setLayout(new GridLayout(0, 3));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add (jp , BorderLayout.SOUTH);
add (jtf, BorderLayout.NORTH);
setLocationRelativeTo (null);
pack ();
setVisible(true);
// end constructor
}
void clickN (String n) {
jtf.setText ("Hit: " + n);
// end method clickN
}
public static void main(String args[]) {
new LambdaExampleND ();
// end main
}
} // end class LambdaExampleND
// File: Sort002.java
// Author: Nicholas Duchon
// Date: Sep 24, 2015
// Start with MyIFm.java and simplify with lambda expressions
//
// NOW:
// > MyButton class added to simplify button setup
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Collections;
interface MKI <X> {
ArrayList <X> makeRandom (int a, int b);}
public class Sort002 <T extends Comparable <T> & MKI <T> > extends JFrame {
static final long serialVersionUID = -3804044462946113366L;
static int startNumber = 20;
static int maxNumber = 1000;
static String colLabel = String.format ("%10s%10s%10s%10s\n", "One", "Two", "Three", "Four");
ArrayList <T> arr; T tint;
// input and output text areas
private JTextField asf = new JTextField("" + startNumber);
private JTextField asg = new JTextField("" + maxNumber);
private JTextArea ioArea = new JTextArea (10,10);
public Sort002 (T t) {
tint = t;
fillArray(startNumber);
setSize (500,500);
// TextArea always get auto scrolls
ioArea.setEditable (true);
ioArea.setFont (new java.awt.Font ("Monospaced", java.awt.Font.PLAIN, 12));
JScrollPane spTextIO = new JScrollPane (ioArea);
// create and add buttons to control panel
JPanel textIObp = new JPanel (new GridLayout (2, 4)); // button panel
textIObp.add(asf);
asf.addActionListener (e -> fillArray (asf.getText()));
textIObp.add(asg);
asg.addActionListener (e -> fillArray (asf.getText(), asg.getText()));
textIObp.add(new MyButton002 ("New Array" , e -> fillArray (asf.getText())));
textIObp.add(new MyButton002 ("Shuffle Array", e -> {Collections.shuffle(arr); display();}));
textIObp.add(new MyButton002 ("Sort on one" , e -> sortMe (1)));
textIObp.add(new MyButton002 ("Sort on two" , e -> sortMe (2)));
textIObp.add(new MyButton002 ("Sort on three", e -> sortMe (3)));
textIObp.add(new MyButton002 ("Sort on four" , e -> sortMe (4)));
add (spTextIO, BorderLayout.CENTER);
add (textIObp, BorderLayout.SOUTH);
setLocationRelativeTo (null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible (true);
display();
} // end T constructor
public void sortMe (int i) {
MyRecord002.column = i;
Collections.sort (arr);
display ();
} // end sortMe
void fillArray (int size) {
// interface method cannot be static, thus the dummy tint.
arr = tint.makeRandom (size, maxNumber);
} //end method fillArray
void fillArray (String st) {
try {
fillArray (Integer.parseInt(st.trim()));
display();
}
catch (NumberFormatException ex) {
ioArea.setText ("Bad number format");
} // end try/catch
} //end method fillArray
void fillArray (String st, String su) {
try {
maxNumber = Integer.parseInt(su.trim());
fillArray (st);
}
catch (NumberFormatException ex) {
ioArea.setText ("Bad number format");
} // end try/catch
} //end method fillArray
public void display () {
ioArea.setText (colLabel);
for (T m: arr)
ioArea.append(m + "\n");
ioArea.append ("done!");
ioArea.setCaretPosition (0);
} // end method display
public static void main (String args[]) {
Sort002 <MyRecord002> m = new Sort002 <> (new MyRecord002(1,1,1,1));
} // end main
} // end class MyIFm
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class MyRecord002 implements Comparable <MyRecord002>, MKI <MyRecord002> {
static java.util.Random rn = new java.util.Random();
static int column = 1;
int one, two, three, four;
public MyRecord002 (int p1, int p2, int p3, int p4) {
one = p1;
two = p2;
three = p3;
four = p4;
} // end 4 int parameter constructor
public ArrayList <MyRecord002> makeRandom (int size, int max) {
ArrayList <MyRecord002> arr = new ArrayList <> (size);
for (int i = 0; i < size; i++)
arr.add (new MyRecord002 (i, rn.nextInt(max), rn.nextInt(max), rn.nextInt(max)));
return arr;
} // end method makeRandom
public int compareTo (MyRecord002 m) {
switch (column) {
case 2:
return two - m.two;
case 3:
return three - m.three;
case 4:
return four - m.four;
case 1:
default:
return one - m.one;
}
} // end compareTo
public String toString () {
return String.format ("%10d%10d%10d%10d", one, two, three, four);
} // end method toString
} // end class MyRecord
class MyButton002 extends JButton {
public static final long serialVersionUID = 92349873;
public MyButton002 (
String ps , // the String parameter, the label of the button
// the following is the second parameter
// the function to call when this button is pressed
// note that each button in the definitions above calls a different method
java.util.function.Consumer
< java.awt.event.ActionEvent > ae
) {
super (ps); // tells the parent class what to use as the label for this button
// the following is the lambda expression used to call the method
// parameter.
addActionListener(e -> ae.accept (e));
} // end MyButton constructor
} // end class MyButton
As the Oracle Language Specification points out, this operator
can be used to reference the invocation of a method without
actually performing the invocation.
There are lots of examples in section 15.13, and here are a few
that seem interesting in our classes.
This code uses the class FrameND.java to create the basic JFrame:
// File: Colons001.java
// Date: Nov 9, 2017
// Author: Nicholas Duchon
// Purpose: experiments with :: operator
// method reference expressions and how to use them
import java.awt.Color;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Colons001 extends FrameND {
public static final long serialVersionUID = 123; // ND: junk
JButton jbA = new JButton ("Press me A");
JButton jbB = new JButton ("Press me B");
JButton jbC = new JButton ("Press me C");
One one = new One ();
public Colons001 () {
super (":: Experiments", 200, 300);
JPanel jp = new JPanel ();
jp.setBackground (Color.yellow);
jp.add (jbA);
jp.add (jbB);
jp.add (jbC);
add (jp, BorderLayout.CENTER);
jbA.addActionListener (e -> System.out.println ("hi"));
jbB.addActionListener (this::fun ); // object::function format
jbC.addActionListener (one ::funOne ); // object::function format
validate ();
} // end constructor
// Since addActionListener is an interface defing ONE method
// and that method has a parameter of type ActionEvent
// the following method MUST have the same parameter list
// in order to use the this::fun protocol
void fun (java.awt.event.ActionEvent e) {
System.out.println (" - Having fun");
} // end method run
public static void main (String [] args) {
Colons001 c = new Colons001 ();
} // end main
} // end class Colons001
class One {
void funOne (java.awt.event.ActionEvent e) {
System.out.println ("Event: " + e.toString().replace (",", "\n"));
} // end funOne
} // end class One
Notes:
Here's some confusing code:
// File: Colons002.java
// Date: Nov 9, 2017
// Author: Nicholas Duchon
// Purpose: sorting with method references
import java.util.Arrays;
// class MyComp implements java.lang.Comparable <String> {
// public int compareTo (String s) {
// return ((String)this).compareTo (s);
// } // end compare method
// } // end class MyComp
// the following does not seem to work at all
// class MyComp implements java.util.Comparator <String> {
class MyComp { // (1) this works with (1) below,
public static int compare (String s, String t) {
return t.replace ("t", "g").compareTo(s.replace("t", "g"));
} // end compare method
} // end class MyComp
public class Colons002 {
public static void main (String [] args) {
System.out.println (Arrays.deepToString (list).replace(",", "\n"));
// (1) the following is ok, but note that MyComp is NOT implementing Comparator!
// Come to think of it, it is not clear why the following works either
// Since MyComp does not implement Comparable, which is supposedly the requirement
// for the Arrays.sort method
// --- sort is a static method, so putting this code into an instance context doesn't
// change the need for static declaration of MyComp.compare
Arrays.sort (list, MyComp::compare);
// The attempts to use classes the implement Comparator and Comparable are
// annoying failures, with compiler errors related to not being
// able to resolve the types of various references
// or not being able to find MyComp.compare (String, String)
// After some more thought, it is hard to understand why the compareTo (T, T)
// method of Comparable <T> is not static - what sense does c make in c.compareTo (T a, T b)?
// Arrays.sort (list, (x, y) -> myComp (x, y)); // ok
// Arrays.sort (list, (x, y) -> y.compareTo (x));
// Arrays.sort (list, (x, y) -> MyComp.compare (x, y));
// Note that the following is not (?) using the implements Comparable interface in the String class
// but the definition of the Arrays.sort method says it requires a Comparator <? super T>
// as the second parameter, and I don't see how this gets past the compiler
// Arrays.sort (list, String::compareTo);
System.out.println ("-------- sorted ------------");
System.out.println (Arrays.deepToString (list).replace(",", "\n"));
} // end main.
static int myComp (String a, String b) {
return b.compareTo (a);
} // end myComp
static String [] list = {"this", "is", "a", "discussion", "for", "students", "to", "ask", "the",
"professor", "questions", "note", "your", "posts", "will", "be", "visible", "to", "your", "classmates",
"if", "you", "have", "a", "specific", "question", "about", "your", "coursework", "or", "your",
"grade", "please", "use", "the", "professor", "preferred", "method", "of", "contact"};
} // end class Colons002
Notes?