I have the following design:
I have an Abstract class Instance,
I have a class Library that extends Instance and
I have a class File that also extends Instance
I've created my own linked list implementation and it's defined as follows:
public class List<T extends Instance> implements Iterable {
//some other code here
public Iterator iterator(){
return new ListIterator(this);
}
now I've created a class
public class ListIterator<T extends Instance> implements Iterator<T> {
private List thisList;
private Node current;
public ListIterator(List l){
thisList=l;
current=thisList.head.next;
}
#Override
public boolean hasNext() {
if(current==null)
return false;
return false;
}
#Override
public T next() {
Node temp=current;
current=current.next;
return temp.data;
}
}
Where Node is
public class Node<T extends Instance> {
public Node<T> next;
public Node<T> prev;
public T data;
public Node(T data,Node prev, Node next){
this.data=data;
this.prev=prev;
this.next=next;
}
}
so my problem is as follows: the line return temp.data rises an error:
Type mismatch - cannot convert from Instance to T.
What is wrong with this code?
I'd say that Node.data is a reference to an Instance object? If that is the case, the compiler can't automatically change an Instance to a T, because even though T is an Instance object (T extends Instance), any given Instance might not be a T.
The Java Generics tutorial explains it: http://docs.oracle.com/javase/tutorial/extra/generics/subtype.html
Also, in your List<T> class, you should be specifying Iterator and ListIterator as generic using Iterator<T> and ListIterator<T>, or else the compiler won't be able to handle the generics properly. Your Node reference also needs to be generic: Node<T>
Hence you should be using
private Node<T> current;
and
public T next() {
Node<T> temp=current;
current=current.next;
return temp.data;
}
The compiler will usually warn you when you're using a raw type for a generic class.
Did no one notice the bug:
public boolean hasNext() {
if(current==null)
return false;
return false;
}
This is an invariant. Unless I am missing something, the iterator will very quickly return 0 elements!
Related
One of the advantages of streams is that you can avoid visiting the whole structure for some operations, like anyMatch or filter+findFirst.
However, if you have your own data structure, depending on how you turn it into a stream you may end up visiting it all anyway.
What is the right way to turn a custom tree data type into a stream?
Consider the following example:
interface Tree{
void forEach(Consumer<Integer> c);
}
final class EmptyTree implements Tree{
public void forEach(Consumer<Integer> c){}
}
interface NonEmptyTree extends Tree{}
record Leave(int label) implements NonEmptyTree{
public void forEach(Consumer<Integer> c){
System.out.println("In forEachLeave "+label);
c.accept(label);
}
}
record Node(NonEmptyTree left, NonEmptyTree right) implements NonEmptyTree{
public void forEach(Consumer<Integer> c){
left.forEach(c); right.forEach(c);
}
}
The two main ways to turn a tree into a stream would be
var sb=Stream.<Integer>builder();
myTree.forEach(sb);
sb.build()
or
Stream.of(myTree).mapMulti(Tree::forEach)
However, both of them call forEach, thus both of them will visit all the tree (and call the prints for all the labels, in this example).
How do you implement a .stream() method in the Tree type so that it would not even visit the whole tree if it is not needed? (because of .anyMatch, for example)
Ok, I sorted it.
I'm quite sure that what I'm doing is pretty standard with immutable trees
(parent fields only make sense in mutable trees)
Here is my result, for reference for future programmers doing streams on immutable trees.
The class TreeIterator<E> is the one really relevant to this ordeal.
I could make nested classes to be able to make more stuff private, but as a code example I think it is more clear in this non nested form.
interface Tree<E> extends Iterable<E>{
Tree<E> and(Tree<E> other);
default Tree<E> left(){ return empty(); }
default Tree<E> right(){ return empty(); }
default E label(Supplier<E> orElse){ return orElse.get(); }
#SuppressWarnings("unchecked")
static <E> Tree<E> empty(){ return (Tree<E>)EmptyTree.empty; }
static <E> Tree<E> leaf(E label){ return new Leaf<E>(label); }
default Stream<E> stream(){ return StreamSupport.stream(spliterator(), false); }
}
final class EmptyTree<E> implements Tree<E>{
public Tree<E> and(Tree<E> other){ return other; }
private EmptyTree(){} //Singleton pattern: only one EmptyTree can exists
static final Tree<?> empty = new EmptyTree<>();
public Iterator<E> iterator(){ return List.<E>of().iterator(); }
public String toString(){ return "<EMPTY>"; }
}
interface NonEmptyTree<E> extends Tree<E>{
Leaf<E> itAdvance(ArrayList<NonEmptyTree<E>> stack);
default Tree<E> and(Tree<E> other){
if (!(other instanceof NonEmptyTree<E> net)){ return this; }
return new Node<E>(this, net);
}
}
record Leaf<E>(E label) implements NonEmptyTree<E>{
public E label(Supplier<E> orElse){ return label; }
public Leaf<E> itAdvance(ArrayList<NonEmptyTree<E>> stack){ return this; }
public Iterator<E> iterator(){ return List.<E>of(label).iterator(); }
public String toString(){ return label+""; }
}
record Node<E>(NonEmptyTree<E> left, NonEmptyTree<E> right) implements NonEmptyTree<E>{
public Node{ assert left!=null && right!=null; }//null is not a valid tree
public Leaf<E> itAdvance(ArrayList<NonEmptyTree<E>> stack){
stack.add(right);
return left.itAdvance(stack);
}
public Iterator<E> iterator(){ return new TreeIterator<E>(this); }
public String toString(){ return "("+left+", "+right+")"; }
}
class TreeIterator<E> implements Iterator<E>{
private final ArrayList<NonEmptyTree<E>> stack = new ArrayList<>(32);
public boolean hasNext(){ return !stack.isEmpty(); }
public TreeIterator(Node<E> n){ stack.add(n); }
public E next(){
if(stack.isEmpty()){ throw new NoSuchElementException(); }
var last=stack.remove(stack.size()-1);
return last.itAdvance(stack).label();
}
}
Looking at record definition Leave(int label) implements NonEmptyTree, I have two questions:
Did you mean "leaf"?
A tree consists of nodes (either a leaf or an internal node), but a node or leaf do not implement a tree, i.e., they are not are specific type of a tree. Are you sure about your node/leaf/tree implementation?
I would recommend a simple implementation like this one here: https://www.baeldung.com/java-binary-tree
When it comes to stream, you have two options:
Implement your own Stream-enabled class (see discussion here)
Provide a method that returns a (specific) stream, e.g. filtered.
Keep in mind that there are many different trees out there, e.g. red–black tree, n-ary tree, AVL Tree, B-Tree ...
I currently have a project that requires the use of abstraction and generics, but I don't even know where I should start for this. The abstract class is as follows.
public abstract class Links<AType> {
abstract AType getElem(); //returns the head of the list
abstract Links<AType> getNext(); //return the next link
}
This is the class that extends the abstract class
public class Cons<AType> extends Links<AType> {
AType elem;
Links<AType> next;
Cons(AType elem, Links<AType> next) {
this.elem = elem;
this.next = next;
}
#Override
AType getElem() {
return elem;
}
#Override
Links<AType> getNext() {
return next;
}
}
Here's another class that extends the abstract class
public class Nil<AType> extends Links<AType> {
Nil(){}
#Override
AType getElem() {
return null;
}
#Override
Links<AType> getNext() {
return null;
}
}
And here is the class that is supposed to implement everything
public class LList<AType> {
Links<AType> list;
LList() {
list = new Cons<>();
}
Links<AType> getList() {
return list;
}
AType get(int n, AType a) {
Cons<AType> aTypeCons = new Cons<>(a, list);
return null;
}
void add(AType elem) {
//add to head of list
}
void remove(int i) {
//remove ith element
//do nothing if i is invalid
}
void print() {
//prints the list
}
}
I just need some help figuring out where to actually start in making the LList class. I can't figure out the constructor because Links is abstract, so I can't make that an object, and I can't make a new Cons<> because there are no elements that are passed into the constructor. However, the constructor is supposed to instantiate a new list. I also can't figure out how I'm supposed to be able to access an individual element of that list. If I can just have a bit of understanding of what needs to happen in the constructor, I should be able to figure out how to implement the rest of the methods.
Your LList is a singly-linked list, where each element has a value and a link to the list that follows. The final element of the list will always be a Nil object, which represents an empty list. When you first initialize an empty list, you can just assign list = new Nil<>();. When you add an element to the list, you can reassign it as list = new Cons<>(elem, list);.
To access an an element in the list by index, just use a while loop that calls getNext() until it's either reached the desired index or found the end of the list.
AType get(int n) {
Links<AType> current = list;
while (n > 0 && current instanceof Cons) {
current = current.getNext();
n--;
}
return current.getElem();
}
I am writing an iterator inner class that iterates through a list. Besides the remove method, I believe I have implemented all the methods of iterator correctly but I get an error saying "Bound mismatch: The type E is not a valid substitute for the bounded parameter > of the type List.Node". I believe this has to with having Node> implements Iterable at the top of my code but I do not want to change that if unneeded. Any possible suggestions on what I should do?
public class List<T extends Comparable<L>> implements Iterable<L> {
private class Node<N extends Comparable<N>> {
private N data;
private Node<N> next;
}
protected Node<L> head;
public Iterator<L> iterator() {
return new ListIterator<L>();
}
public class ListIterator<E extends Comparable<E>> implements Iterator<E> {
private Node<E> N = (Node<E>) head; //"Bound mismatch: The type E is not a valid substitute for the bounded parameter <D extends Comparable<D>> of the type List<T>.Node<D>"
public boolean hasNext() {
return (N.next != null);
}
public E next() {
if (!hasNext())
throw new NoSuchElementException();
else {
N = N.next;
return N.data;
}
}
public void remove() {
}
}
}
You should reduce the number of generic types. Because the inner classes know the generic type of their parent class, you should simplify the Node and ListIterator class:
public class List<L extends Comparable<L>> implements Iterable<L> {
private class Node {
private L data;
private Node next;
}
protected Node head;
public Iterator<L> iterator() {
return new ListIterator();
}
public class ListIterator implements Iterator<L> {
private Node N = head;
public boolean hasNext() {
return (N.next != null);
}
public L next() {
if (!hasNext())
throw new NoSuchElementException();
else {
N = N.next;
return N.data;
}
}
public void remove() {
}
}
}
The type parameter N is declared as
N extends Comparable<N>
ie. it has bounds. It must be Comparable to itself.
The type parameter E is declared as
E
ie. it has no bounds. It can be any type, but not necessarily a type that is Comparable to itself.
Therefore, you can't use E where an N is expected. Consider adding the same bounds as N to E.
I've been working on this program for a few days now and I've implemented a few of the primary methods in my BinarySearchTree class such as insert and delete. Insert seemed to be working fine, but once I try to delete I kept getting errors. So after playing around with the code I wanted to test my compareTo methods. I created two new nodes and tried to compare them and I get this error:
Exception in thread "main" java.lang.ClassCastException: TreeNode cannot be cast to java.lang.Integer
at java.lang.Integer.compareTo(Unknown Source)
at TreeNode.compareTo(TreeNode.java:16)
at BinarySearchTree.myComparision(BinarySearchTree.java:177)
at main.main(main.java:14)
Here is my class for creating the nodes:
public class TreeNode<T> implements Comparable
{
protected TreeNode<T> left, right;
protected Object element;
public TreeNode(Object obj)
{
element=obj;
left=null;
right=null;
}
public int compareTo(Object node)
{
return ((Comparable) this.element).compareTo(node);
}
}
Am I doing the compareTo method all wrong? I would like to create trees that can handle integers and strings (seperatly of course)
To be sure that the element indeed is a comparable object, and avoid all the casts, you could do something like this:
public class TreeNode<T extends Comparable<? super T>>
implements Comparable<TreeNode<T>> {
protected TreeNode<T> left, right;
protected T element;
public TreeNode(T obj) {
element = obj;
left = null;
right = null;
}
#Override
public int compareTo(TreeNode<T> node) {
return element.compareTo(node.element);
}
}
For an usage example:
TreeNode<Integer> node1 = new TreeNode<Integer>(2);
TreeNode<Integer> node2 = new TreeNode<Integer>(3);
System.out.println(node1.compareTo(node2));
The above snippet prints -1 on the console.
compareTo method is applied against TreeNode (passed as node parameter), while you compare it with this.element, which is an Object contained in the TreeNode. Simply change to:
return ((Comparable) this.element).compareTo(node.getElement());
assuming you have getElement method.
Try
public <T> int compareTo(Object node)
{
return ((Comparable) this.element).compareTo( ( TreeNode<T> ) node ).element);
}
I am implementing a sorted list using linked lists. My node class looks like this
public class Node<E>{
E elem;
Node<E> next, previous;
}
In the sorted list class I have the add method, where I need to compare generic objects based on their implementation of compareTo() methods, but I get this syntax error
"The method compareTo(E) is undefined for type E". I have tried implemnting the compareTo method in Node, but then I can't call any of object's methods, because E is generic type.
Here is the non-finished body of add(E elem) method.
public void add(E elem)
{
Node<E> temp = new Node<E>();
temp.elem = elem;
if( isEmpty() ) {
temp.next = head;
head.previous = temp;
head = temp;
counter++;
}else{
for(Node<E> cur = head; cur.next != null ; cur= cur.next) {
**if(temp.elem.comparTo(cur.elem)) {**
//do the sort;
}/*else{
cur.previous = temp;
}*/
}
//else insert at the end
}
}
Here is one of the object implemnting compareTo method
public class Patient implements Comparable<Patient>{
public int compareTo(Patient that)
{
return (this.getPriority() <= that.getPriority() ? 1 : 0 );
}
}
Bound E to Comparable:
public class Node<E extends Comparable<E>>{
E elem;
Node<E> next, previous;
}
It will compile now.
If you want the elements stored in your nodes to be comparable, you can state this using generics:
public class Node<E extends Comparable<E>> {
E elem;
Node<E> next, previous;
}
this way it is sure, that every E implements the Comparable interface, so you can safely call the compareTo method.
It seems that your generic E must be E extends Comparable<E>. This way you will get the access to the compareTo(E other) method. However, you will be unable to add elements that are not implementing this interface.
Try
public class Node<E extends Comparable<E>>{
E elem;
Node<E> next, previous;
}