Interfaces - Exercises
Iterators
wouldn't it be nice to iterate through any Collection or array easily like this
class MainClass {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList();
int[] ints = {100, 200, 300};
for (int i = 0; i <= 50 ; i+=10)
list.add(i);
for (int elem : list)
System.out.print(elem + "\t");
System.out.println();
for (int elem : ints)
System.out.print(elem + "\t");
}
}
0 10 20 30 40 50
100 200 300
we can use the power of iterators
example
import java.util.Iterator;
class Main {
public static void main(String[] args) {
IntList list = new IntList();
System.out.println(list);
for (int i = 0; i <= 30; i+=10)
list.add(i);
System.out.println(list); // IntList{size=4, capacity=10, elements=[0, 10, 20, 30]}
//First way
Iterator<Integer> it = list.iterator();
while(it.hasNext())
System.out.print(it.next() + " ,"); //Integer i = it.next();
System.out.println();
//2nd way, easier to use
for (int elem : list)
System.out.print(elem + " ,");
}
}
IntList{size=0, capacity=10, elements=[]}
IntList{size=4, capacity=10, elements=[0, 10, 20, 30]}
0 ,10 ,20 ,30 ,
0 ,10 ,20 ,30 ,
our IntList now implements
Iterable
As we can see we call the iterator
function (another name would implement (override) the Iterator) and return an object of type Iterator
iterator
has 2 functions
hasNext()
return booleannext()
returns the next item
now we can use a for-each
🤔 How would write an iterator for a linkedList? Its not so difficult
Comparator
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
class MainClass {
public static void main(String[] args) {
ArrayList<Point> list = new ArrayList();
list.add(new Point(0,0));
list.add(new Point(10,10));
list.add(new Point(0,-10));
list.add(new Point(0,-0));
list.add(new Point(-10,-10));
list.add(new Point(5,5));
list.add(new Point(10,0));
Collections.sort(list);
System.out.println("========= sorting list ===========");
for(Point point: list)
System.out.println(point);
// ========= sorting arrays ===========
System.out.println("========= sorting arrays ===========");
Point[] arr = new Point[7];
arr[0] = new Point(0,0);
arr[1] = new Point(10,10);
arr[2] = new Point(0,-10);
arr[3] = new Point(-10,-10);
arr[4] = new Point(5,5);
arr[5] = new Point(10,0);
arr[6] = new Point(0,0);
Arrays.sort(arr);
for(Point point: arr)
System.out.println(point);
}
}
========= sorting list ===========
Point { x=-10.0, y=-10.0 }
Point { x=0.0, y=-10.0 }
Point { x=0.0, y=0.0 }
Point { x=0.0, y=0.0 }
Point { x=10.0, y=0.0 }
Point { x=5.0, y=5.0 }
Point { x=10.0, y=10.0 }
========= sorting arrays ===========
Point { x=-10.0, y=-10.0 }
Point { x=0.0, y=-10.0 }
Point { x=0.0, y=0.0 }
Point { x=0.0, y=0.0 }
Point { x=10.0, y=0.0 }
Point { x=5.0, y=5.0 }
Point { x=10.0, y=10.0 }
change in Point
implemented Comparable, now we can sort
overrided
compareTo
function
class Point implements Comparable<Point> {
//...
@Override
public int compareTo(Point other) {
// First sort by Y
// Then sort by X
if (this.equals(other)) {
return 0;
}else if (y != other.y){
return (y > other.y) ? 1 : -1;
}else { //if (y == other.y)
return (x > other.x) ? 1 : -1;
}
}
}
Test Question


Note: the answer can be much simpler but I trying to teach a few ideas
class Main {
public static void main(String[] args) {
StdDraw.setXscale(0, 100);
StdDraw.setYscale(0, 100);
PointContainer polygon1 = new PointContainer();
polygon1.add(new Point(20,20));
polygon1.add(new Point(80,20));
polygon1.add(new Point(50,70));
polygon1.sort();
polygon1.close();
System.out.println(polygon1);
polygon1.draw();
//use iterator
for (Point p : polygon1)
System.out.print(p + "\t");
}
}
Polygon{size=4, capacity=10, elements=[Point { x=20.0, y=20.0 }, Point { x=80.0, y=20.0 }, Point { x=50.0, y=70.0 }, Point { x=20.0, y=20.0 }]}
Point { x=20.0, y=20.0 } Point { x=80.0, y=20.0 } Point { x=50.0, y=70.0 } Point { x=20.0, y=20.0 }
or this
import java.util.ArrayList;
class MainClass {
public static void main(String[] args) {
ArrayList<PointContainer> polygons = new ArrayList<>();
StdDraw.setXscale(0, 500);
StdDraw.setYscale(0, 500);
polygons.add(new PointContainer(new Point[]{new Point(229, 153), new Point(160,218), new Point(177,325), new Point(249,268)} )) ;
polygons.get(0).sort().close();
polygons.add(new PointContainer(new Point[]{new Point(249,268), new Point(177,325),new Point(269,336), new Point(349,283) } ));
polygons.get(1).sort().close().setColor(0,255,0);
polygons.add(new PointContainer(new Point[]{new Point(349,283), new Point(328,182),new Point(229,153), new Point(249,268) } ));
polygons.get(2).sort().close().setColor(255,0,0); // remove sort to fix messed up polygon
for (PointContainer p : polygons){
p.draw();
System.out.println(p);
}
}
}
Polygon{size=5, capacity=8, elements=[Point { x=160.0, y=218.0 }, Point { x=229.0, y=153.0 }, Point { x=249.0, y=268.0 }, Point { x=177.0, y=325.0 }, Point { x=160.0, y=218.0 }]}
Polygon{size=5, capacity=8, elements=[Point { x=249.0, y=268.0 }, Point { x=177.0, y=325.0 }, Point { x=269.0, y=336.0 }, Point { x=349.0, y=283.0 }, Point { x=249.0, y=268.0 }]}
Polygon{size=5, capacity=8, elements=[Point { x=229.0, y=153.0 }, Point { x=249.0, y=268.0 }, Point { x=328.0, y=182.0 }, Point { x=349.0, y=283.0 }, Point { x=229.0, y=153.0 }]}
we could also use
public PointContainer sort() {
Arrays.sort(elements);
return this;
}
if we implement Comparator
import java.util.Comparator;
import java.util.Objects;
class Point implements Comparator<Point>, Comparable<Point> {
public double x, y;
//...
@Override
public int compare(Point p1, Point p2) {
if (p1 == null && p2 == null) {
return 0;
}
if (p1 == null) {
return 1;
}
if (p2 == null) {
return -1;
}
return p1.compareTo(p2);
}
@Override
public int compareTo(Point other) {
// euclidean distance
if (this.equals(other))
return 0;
//same distance then check Ys
if (distance(new Point(), this) == distance(new Point(), other)){
if (y != other.y)
return y > other.y ? 1 : -1;
else
return x > other.x ? 1 : -1;
}
//if distance is not the same
return (distance(new Point(), this) > distance(new Point(), other)) ? 1 : -1;
}
}
or even doing this
public class PointContainer implements Iterable<Point>{
//... add before
public PointContainer sort() {
Arrays.sort(elements, new Comparator<Point>() {
@Override
public int compare(Point p1, Point p2) {
if (p1 == null && p2 == null) {
return 0;
}
if (p1 == null) {
return 1;
}
if (p2 == null) {
return -1;
}
return p1.compareTo(p2);
}
});
return this;
}
//==== add iterator =========
}
class Point implements Comparable<Point> {
//now there is no compare(Point p1, Point p2)
@Override
public int compareTo(Point other) {
// euclidean distance
if (this.equals(other))
return 0;
//same distance then check Ys
if (distance(new Point(), this) == distance(new Point(), other)){
if (y != other.y)
return y > other.y ? 1 : -1;
else
return x > other.x ? 1 : -1;
}
//if distance is not the same
return (distance(new Point(), this) > distance(new Point(), other)) ? 1 : -1;
}
}
Exercise: Student and Grade
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("moshe", 25));
students.get(0).add(new Grade("infi", 95));
students.get(0).add(new Grade("java", 100));
//add more students
Collections.sort(students);
for (Student s : students)
System.out.println(s);
}
and get something like this
Student{name='moshe', age=25, avg_grades=97.66666666666667, grades=[{sub='infi', grade=95.0}, {sub='java', grade=100.0}, {sub='data structures', grade=98.0}]}
Student{name='aviv', age=28, avg_grades=87.66666666666667, grades=[{sub='infi', grade=100.0}, {sub='java', grade=65.0}, {sub='data structures', grade=98.0}]}
Student{name='rachel', age=23, avg_grades=85.0, grades=[{sub='infi', grade=80.0}, {sub='java', grade=75.0}, {sub='data structures', grade=100.0}]}
we are sorting by the grade average
We will need to make 2 classes
Grade
String subject
double grade
Student
static int rollno
String name
int age
List<Grade> grades
solution
class Main {
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("moshe", 25));
students.add(new Student("rachel", 23));
students.add(new Student("aviv", 28));
students.get(0).add(new Grade("infi", 95));
students.get(0).add(new Grade("java", 100));
students.get(0).add(new Grade("data structures", 98));
students.get(1).add(new Grade("infi", 80));
students.get(1).add(new Grade("java", 75));
students.get(1).add(new Grade("data structures", 100));
students.get(2).add(new Grade("infi", 100));
students.get(2).add(new Grade("java", 65));
students.get(2).add(new Grade("data structures", 98));
Collections.sort(students);
for (Student s : students)
System.out.println(s);
}
}
Student{name='moshe', age=25, avg_grades=97.66666666666667, grades=[{sub='infi', grade=95.0}, {sub='java', grade=100.0}, {sub='data structures', grade=98.0}]}
Student{name='aviv', age=28, avg_grades=87.66666666666667, grades=[{sub='infi', grade=100.0}, {sub='java', grade=65.0}, {sub='data structures', grade=98.0}]}
Student{name='rachel', age=23, avg_grades=85.0, grades=[{sub='infi', grade=80.0}, {sub='java', grade=75.0}, {sub='data structures', grade=100.0}]}
we don't have to implement Iterator since we are using Java Arraylist
GUIs - Not on the test!
what else can we use interfaces for?
for GUIs
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class Main extends JFrame {
public static void main(String[] args) {
JFrame frame = new JFrame("My First GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300,300);
JButton button1 = new JButton("Add 1");
JButton button2 = new JButton("Add 5");
frame.getContentPane().add(BorderLayout.NORTH, button1);
frame.getContentPane().add(BorderLayout.SOUTH, button2);
JLabel jlabel = new JLabel("you clicked me 0 times");
frame.getContentPane().add(BorderLayout.CENTER, jlabel);
final int[] counter = {0};
// ============= important stuff ============
// here we implement the ActionListener interface
button1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("you clicked me " + ++counter[0] + " times");
jlabel.setText("you clicked me " + counter[0] + " times");
}
});
button2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("you clicked me " + (counter[0]+=5) + " times");
jlabel.setText("you clicked me " + (counter[0]) + " times");
}
});
frame.setVisible(true);
}
}
ActionListener is an interface we implement add to the addActionListener()
on a button
Last updated
Was this helpful?