Java: Implementation of double-chained list (deque) with callback, generics, exception and lambda [closed]

0

I'm doing the implementation in java, however I have some problems with how to integrate generics and lambda in the deque:

Deque.java :

import java.util.ArrayList;
public class Deque {
    private Element head;
    private Element tail; 
    public Deque() {
        head = tail = null;
    }
    public boolean isEmpty() {
        return head == null && tail == null;
    }
    public boolean isFull() {
        return false;
    }
    public ArrayList<Integer> List() throws EmptyListException { //generics and exception
        ArrayList<Integer> list = new ArrayList<Integer>();     
        if(head == null)
            throw new EmptyListException("The list is empty!");     
        else{
            Element elementFirst = getFirst();          
            while(elementFirst != null){
                int value = elementFirst.getValue(); 
                list.add(value);
                elementFirst = elementFirst.getNext();
            }
            return list;
        }       
    }
    public void addFirst(Object o) {
        System.out.println("Addited in first: " + o);
        Element e = new Element(o);
        e.setNext(head); 

        if(head != null) {
            head.setPrev(e);  
        }
        head = e; 
        if(tail == null) {
            tail = e; 
        }
    }
    public void addLast(Object o) throws Exception {
        System.out.println("Addited in last: " + o);
        Element e = new Element(o);
        e.setPrev(tail); 

        if(tail != null) {
            tail.setNext(e);
        }
        tail = e;
        if(head == null) {
            head = e;
        }
    }
    public Object removeFirst() throws Exception {
        if(this.isEmpty()) {
            throw new Exception ("The Queue is empty!");
        } else {
            Object o = head.getValue();
            head = head.getNext(); 
            if(head == null) { 
                tail = null;
            } else {
                head.setPrev(null); 
            }
            System.out.println("Removed in first: " + o);
            System.out.println("New head: " + head.getValue());
            return o;
        }
    }
    public Object removeLast() throws Exception {
        if(this.isEmpty()) {
            throw new Exception ("The Queue is empty!");
        } else {
            Object o = tail.getValue();
            tail = tail.getPrev(); 
            if(tail == null) {
                head = null;
            } else {
                tail.setNext(null); 
            }
            System.out.println("Removed in last: " + o);
            System.out.println("New tail: " + tail.getValue());
            return o;
        }
    }
    public void clear() {
        System.out.println("");
        System.out.println("Start clear... ");
        while (!this.isEmpty()) {
            try {
                this.removeFirst();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("End clear");
        System.out.println("");
    }
    public void listing() {
        Element e = head;
        System.out.println("");
        System.out.println("Start listing... ");
        while (e != null) {
            System.out.println("Value: " + e.getValue());
            e = e.getNext();
        }
        System.out.println("End listing");
        System.out.println("");
    }
}

Element.java :

public class Element {
    private Element next;
    private Element prev;
    private Object value;
    public Element (Object v) {
        value = v;
    }
    public void setNext(Element e) {
        this.next = e;
    }
    public Element getNext() {
        return next;
    }
    public void setPrev(Element e) {
        this.prev = e;
    }
    public Element getPrev() {
        return prev;
    }
    public void setValue(Object value) {
        this.value = value;
    }
    public Object getValue() {
        if(value != null) {
            System.out.println("the value is null!");
            return false;
        }
        return value;
    }
}

Main.java :

public class Main {
    public static void main(String[] args) throws Exception { 
        Deque deque = new Deque(); 

        do{         
            System.out.println("Select the option\n 1->Add first:\n 2->Add last:\n3->List:\n 4->Remove first:\n 5->Remove last:\n 6->Clear:\n 7->Exit:\n");     
            option = scanner.next();            
            if(option == 1){
                System.out.println("Enter with the value: ");
                value = scanner.next();
                deque.addFirst(value);
            }               
            else if(option == 2){
                System.out.println("Enter with the value: ");
                value = scanner.next();
                deque.addLast(value);       
            }                   
            else if(option == 3){
                ArrayList<String> myList = new ArrayList<String>();
                try {
                    myList = deque.List();
                    //deque.listing();
                } 
                catch (EmptyListException e) {
                    e.printStackTrace();                    
                }
            }
            else if(option == 4){
                deque.removeFirst();        
            }
            else if(option == 5){
                deque.removeLast(); 
            }
            else if(option == 6){
                deque.clear();
            }
            else {
                System.out.println("Invalid option");
            }
        }
        while(option != "7");
    }
}
    
asked by anonymous 19.06.2018 / 18:33

1 answer

6

Let's start with Element :

public class Element<T> {
    private Element<T> next;
    private Element<T> prev;
    private T value;

    public Element(T v) {
        value = v;
    }

    public void setNext(Element<T> e) {
        this.next = e;
    }

    public Element<T> getNext() {
        return next;
    }

    public void setPrev(Element<T> e) {
        this.prev = e;
    }

    public Element<T> getPrev() {
        return prev;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public T getValue() {
        /*if(value != null) {
            System.out.println("the value is null!");
            return false;
        }*/
        return value;
    }
}

This return false; of getValue() is harmful. It prevents you from using generic types there. Also, if the content of Element is null , that the getValue() method returns that null .

The class EmptyListException :

public class EmptyListException extends Exception {
    public EmptyListException(String message) {
        super(message);
    }
}

Now the class Deque :

import java.util.ArrayList;
import java.util.List;

public class Deque<T> {
    private Element<T> head;
    private Element<T> tail; 

    public Deque() {
        head = tail = null;
    }

    public boolean isEmpty() {
        return head == null && tail == null;
    }

    public boolean isFull() {
        return false;
    }

    public List<T> toList() {
        List<T> list = new ArrayList<>();     
        Element<T> elementFirst = getFirst();          
        while (elementFirst != null) {
            T value = elementFirst.getValue(); 
            list.add(value);
            elementFirst = elementFirst.getNext();
        }
        return list;     
    }

    public void addFirst(T o) {
        System.out.println("Addited in first: " + o);
        Element<T> e = new Element<>(o);
        e.setNext(head); 

        if (head != null) {
            head.setPrev(e);  
        }
        head = e; 
        if (tail == null) {
            tail = e; 
        }
    }

    public void addLast(T o) {
        System.out.println("Addited in last: " + o);
        Element<T> e = new Element<>(o);
        e.setPrev(tail); 

        if (tail != null) {
            tail.setNext(e);
        }
        tail = e;
        if (head == null) {
            head = e;
        }
    }

    public T removeFirst() throws EmptyListException {
        if (this.isEmpty()) {
            throw new EmptyListException("The deque is empty!");
        }
        T o = head.getValue();
        head = head.getNext(); 
        if (head == null) { 
            tail = null;
        } else {
            head.setPrev(null); 
        }
        System.out.println("Removed in first: " + o);
        System.out.println("New head: " + head.getValue());
        return o;
    }

    public T removeLast() throws EmptyListException {
        if (this.isEmpty()) {
            throw new EmptyListException("The deque is empty!");
        }
        T o = tail.getValue();
        tail = tail.getPrev(); 
        if (tail == null) {
            head = null;
        } else {
            tail.setNext(null); 
        }
        System.out.println("Removed in last: " + o);
        System.out.println("New tail: " + tail.getValue());
        return o;
    }

    public void clear() {
        System.out.println("");
        System.out.println("Start clear... ");
        while (!this.isEmpty()) {
            this.removeFirst();
        }
        System.out.println("End clear");
        System.out.println("");
    }

    public void listing() {
        Element<T> e = head;
        System.out.println("");
        System.out.println("Start listing... ");
        while (e != null) {
            System.out.println("Value: " + e.getValue());
            e = e.getNext();
        }
        System.out.println("End listing");
        System.out.println("");
    }
}

Here are several things to note:

  • In method List() (rename to toList() ) you used ArrayList<Integer> . This presumably assumed that the deque type was Integer instead of T .

  • Using throws Exception is a bad programming practice, as you should declare the throwing of specific exceptions instead of generic exceptions. Likewise, throw new Exception(...) is also bad practice for the same reason. When using EmptyListException , the specific exception is declared and thrown, rather than the generic exception.

  • And third that calling the toList() method on an empty deck has no problem, the result will be just an empty list.

  • Do not declare variables of type ArrayList . Although you can use the ArrayList constructor, it is best to declare the variable type with List only. The reason for this is that there is a programming principle that tells you to code for an interface ( List ) and not for an implementation ( ArrayList ). When you do this, you can interoperate with other types of lists (such as LinkedList or lists returned by methods such as Arrays.asList(...) , Collections.unmodifiableList(...) or List.of(...) ).

  • Finally, let's see your Main :

    import java.util.List;
    
    public class Main {
        public static void main(String[] args) { 
            Deque<String> deque = new Deque<>();
    
            while (true) {         
                System.out.println("Select the option\n 1->Add first:\n 2->Add last:\n3->List:\n 4->Remove first:\n 5->Remove last:\n 6->Clear:\n 7->Exit:\n");
                String option = scanner.next();
                if ("1".equals(option)) {
                    System.out.println("Enter with the value: ");
                    value = scanner.next();
                    deque.addFirst(value);
                } else if ("2".equals(option)) {
                    System.out.println("Enter with the value: ");
                    value = scanner.next();
                    deque.addLast(value);
                } else if ("3".equals(option)) {
                    List<String> myList = deque.toList();
                    System.out.println(myList);
                    deque.listing();
                } else if ("4".equals(option)) {
                    try {
                        deque.removeFirst();
                    } catch (EmptyListException e) {
                        System.out.println(e.getMessage());
                    }
                } else if ("5".equals(option)) {
                    try {
                        deque.removeLast();
                    } catch (EmptyListException e) {
                        System.out.println(e.getMessage());
                    }
                } else if ("6".equals(option)) {
                    deque.clear();
                } else if ("7".equals(option)) {
                    break;
                } else {
                    System.out.println("Invalid option");
                }
            }
        }
    }
    

    The remarks here are as follows:

  • You had not declared the variable option properly. The next() method of Scanner returns String s, so option would be of type String . This may seem a bit strange considering that the expected values are 1, 2, 3, 4, 5, 6 and 7. However, this allows you to switch to A, B, C, D, E, F and G have problems. Even something like Red, Orange, Yellow, Green, Blue, Anil and Violet would work.

  • I changed do-while to while to prevent Invalid option from appearing when the user wants to exit.

  • I do not know if the listing() method of your Deque is a good idea, since a System.out.println(deque.toList()) would already be enough.

    Oh, finally, there is no lambda or callback (yet) in your code.

        
  • 19.06.2018 / 19:32