Last active
April 18, 2021 10:24
-
-
Save mfaella/43c6b36bdb66cc534edf21fa88dacf27 to your computer and use it in GitHub Desktop.
A list-like class exposing its length as part of its type (see https://medium.com/@marfaella/counting-with-java-generics-ad33c5ef434d)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.*; | |
/** | |
* A linked list that exposes its length as part of its type. | |
* | |
* @author Marco Faella | |
* @version 1.0 | |
*/ | |
public class L<T,N extends L<T,?>> implements Iterable<T> { | |
private T item; | |
private N next; | |
/** Creates a list with one element. */ | |
public L(T item) { | |
this.item = item; | |
} | |
/* Constructor used by add */ | |
private L(T item, N next) { | |
this.item = item; | |
this.next = next; | |
} | |
/** Head insertion. | |
*/ | |
public L<T,L<T,N>> addFirst(T item) { | |
return new L<>(item, this); | |
} | |
@Override | |
public Iterator<T> iterator() { | |
return new Iterator<>() { | |
private L<T,? extends L<T,?>> current = L.this; | |
public boolean hasNext() { | |
return current != null; | |
} | |
public T next() { | |
T result = current.item; | |
current = current.next; | |
return result; | |
} | |
}; | |
} | |
/** This factory method prevents the possibility of declaring | |
a list as longer than it really is. | |
*/ | |
public static <T> L<T,L<T,?>> makeNew(T item) { | |
return new L<>(item); | |
} | |
/** This method can only be called on same-length lists. | |
*/ | |
public static <T,N extends L<T,?>> | |
void sameLength(L<T,N> list1, L<T,N> list2) { | |
System.out.println("Here!"); | |
} | |
public static void main(String...args) { | |
var list1 = new L<>(42); | |
var list2 = list1.addFirst(7); | |
var list3 = list2.addFirst(100); | |
for (Integer i: list3) { | |
System.out.println(i); | |
} | |
sameLength(list3, list3); | |
// Tjis would be a compile-time error: | |
// sameLength(list2, list3); | |
var stringList1 = new L<>("world"); | |
var stringList2 = stringList1.addFirst("Hello "); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment