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    300we 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 + " ,");
    }
}import java.util.Arrays;
import java.util.Iterator;
public class IntList implements Iterable<Integer>{
    /// we we did before
    //add iterator
    @Override
    public Iterator<Integer> iterator() {
        Iterator it = new Iterator() {
            private int currentIndex = 0;
            @Override
            public boolean hasNext() {
                return currentIndex < size;
            }
            @Override
            public Integer next() {
                return elements[currentIndex++];
            }
        };
        return it;
    }
}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);
    }
}class Point implements Comparable<Point>{
    public double x, y;
    //=== constructors ===
    //default constructor
    Point() {
        x = 0;
        y = 0;
    }
    Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    //copy constructor
    Point(Point p) {
        x = p.x; // Since this is the same class I can access without getter/setter
        y = p.y;
    }
    //=== static methods ===
    public static double distance(Point a, Point b) {
        double dist = Math.pow(a.x-b.x, 2) + Math.pow(a.y-b.y, 2);
        return Math.sqrt(dist);
    }
    public String toString() {
        return "Point {" + " x=" + x + ", y=" + y + " }";
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return Double.compare(point.x, x) == 0 && Double.compare(point.y, y) == 0;
    }
    @Override
    public int compareTo(Point other) {
        //  First sort by Y
        //  Then  sort by X
        //  0 is equal, 1 if this is larger, -1 if other is larger
        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;
        }
    }
}========= 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
compareTofunction
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");
    }
}class Point implements Comparable<Point>{
    public double x, y;
    //...
    // ================ Look Here ===================
    @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;
    }
}package com.company;
import java.awt.*;
import java.util.Arrays;
import java.util.Iterator;
//Polyon
public class PointContainer implements Iterable<Point>{
    private int size = 0; // shouldn't be public
    private static final int DEFAULT_CAPACITY = 10;
    private Point[] elements;
    private Color color;
    private String name = new String("");
    //...
    //added new constructor
    public PointContainer(Point[] points) {
        size = points.length;
        elements = Arrays.copyOf(points, size);
        setColor(0,0,255);
    } 
    public PointContainer close() {
        add(new Point(elements[0]));
        return this;
    }
    // ========= This is what sorts ==================
    public PointContainer sort() {
         Arrays.sort(elements, 0, size); // can't use Arrays.sort(elements), since there are nulls
         return this;
    }
    // ========= until here ==================
    //==== add iterator =========
    @Override
    public Iterator<Point> iterator() {
        Iterator it = new Iterator() {
            private int currentIndex = 0;
            @Override
            public boolean hasNext() {
                return currentIndex < size;
            }
            @Override
            public Point next() {
                return elements[currentIndex++];
            }
        };
        return it;
    }
}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);
    }
}    import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Student implements Comparable<Student>{
    static int rollno = 0;
    String name;
    int age;
    List<Grade> grades; //our class
    Student(String name,int age){
        this.rollno= ++rollno;
        this.name=name;
        this.age=age;
        grades = new ArrayList<>();
    }
    public Student add(Grade new_grade){
        grades.add(new_grade);
        return this;
    }
    public double avg_grades(){
        double sum = 0;
        for (Grade g : grades)
            sum += g.grade;
        return sum/grades.size();
    }
    public int compareTo(Student other){
        //sort students by average
        if(grades.size()==0 || (avg_grades() == other.avg_grades()))
            return 0;
        else if(avg_grades() > other.avg_grades())
            return -1;
        else
            return 0;
    }
    @Override
    public String toString() {
        return "Student{" + "name='" + name + '\'' + ", age=" + age + ", "+ "avg_grades=" + avg_grades() + ", grades=" + grades + '}';
    }
}public class Grade {
    public String subject;
    public double grade;
    public Grade(String subject, double grade) {
        this.subject = subject;
        this.grade = grade;
    }
    @Override
    public String toString() {
        return "{" + "sub='" + subject + '\'' + ", grade=" + grade +'}';
    }
}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?