package hjelpeklasser;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class TabellListe<T> implements Liste<T>
{
private T[] a;
private int antall;
private int endringer;
public TabellListe(int størrelse)
{
@SuppressWarnings("unchecked")
T[] b = (T[]) new Object[størrelse];
a = b;
antall = 0;
endringer = 0;
}
public TabellListe()
{
this(10);
}
public TabellListe(T[] b)
{
this(b.length);
for (T verdi : b)
{
if (verdi != null) a[antall++] = verdi;
}
}
private static void fratilKontroll(int antall, int fra, int til)
{
if (fra < 0)
throw new IndexOutOfBoundsException
("fra(" + fra + ") er negativ!");
if (til > antall)
throw new IndexOutOfBoundsException
("til(" + til + ") > antall(" + antall + ")");
if (fra > til)
throw new IllegalArgumentException
("fra(" + fra + ") > til(" + til + ") - illegalt intervall!");
}
public Liste<T> subliste(int fra, int til)
{
fratilKontroll(antall, fra, til);
TabellListe<T> liste = new TabellListe<>(til - fra);
for (int i = fra, j = 0; i < til; i++, j++) liste.a[j] = a[i];
liste.antall = til - fra;
return liste;
}
@Override
public boolean leggInn(T verdi)
{
Objects.requireNonNull(verdi, "null er ulovlig!");
if (antall == a.length)
{
a = Arrays.copyOf(a,(3*antall)/2 + 1);
}
a[antall++] = verdi;
endringer++;
return true;
}
@Override
public void leggInn(int indeks, T verdi)
{
Objects.requireNonNull(verdi, "null er ulovlig!");
indeksKontroll(indeks, true);
if (antall == a.length) a = Arrays.copyOf(a,(3*antall)/2 + 1);
for (int i = antall; i > indeks; i--) a[i] = a[i-1];
a[indeks] = verdi;
antall++;
endringer++;
}
@Override
public int antall()
{
return antall;
}
@Override
public boolean tom()
{
return antall == 0;
}
@Override
public T hent(int indeks)
{
indeksKontroll(indeks, false);
return a[indeks];
}
@Override
public int indeksTil(T verdi)
{
for (int i = 0; i < antall; i++)
{
if (a[i].equals(verdi)) return i;
}
return -1;
}
@Override
public boolean inneholder(T verdi)
{
return indeksTil(verdi) != -1;
}
@Override
public T oppdater(int indeks, T verdi)
{
Objects.requireNonNull(verdi, "null er ulovlig!");
indeksKontroll(indeks, false);
T gammelverdi = a[indeks];
a[indeks] = verdi;
endringer++;
return gammelverdi;
}
@Override
public T fjern(int indeks)
{
indeksKontroll(indeks, false);
T verdi = a[indeks];
antall--;
for (int i = indeks; i < antall; i++) a[i] = a[i + 1];
a[antall] = null;
endringer++;
return verdi;
}
@Override
public boolean fjern(T verdi)
{
Objects.requireNonNull(verdi, "null er ulovlig!");
for (int i = 0; i < antall; i++)
{
if (a[i].equals(verdi))
{
antall--;
for (int j = i; j < antall; j++) a[j] = a[j + 1];
a[antall] = null;
endringer++;
return true;
}
}
return false;
}
@Override
public boolean fjernHvis(Predicate<? super T> p)
{
Objects.requireNonNull(p, "predikatet er null");
int nyttAntall = antall;
for (int i = 0, j = 0; j < antall; j++)
{
if (p.test(a[j])) nyttAntall--;
else a[i++] = a[j];
}
for (int i = nyttAntall; i < antall; i++)
{
a[i] = null;
}
boolean fjernet = nyttAntall < antall;
if (fjernet) endringer++;
antall = nyttAntall;
return fjernet;
}
@Override
@SuppressWarnings("unchecked")
public void nullstill()
{
if (a.length > 10)
a = (T[])new Object[10];
else
for (int i = 0; i < antall; i++)
{
a[i] = null;
}
antall = 0;
endringer++;
}
public String toString2()
{
StringBuilder s = new StringBuilder("[");
if (!tom())
{
s.append(a[0]);
for (int i = 1; i < antall; i++)
{
s.append(',').append(' ').append(a[i]);
}
}
s.append(']');
return s.toString();
}
@Override
public String toString()
{
StringJoiner s = new StringJoiner(", ","[","]");
for (int i = 0; i < antall; i++) s.add(a[i].toString());
return s.toString();
}
@SuppressWarnings("unchecked")
public <T> T[] tilTabell(T[] b)
{
if (b.length < antall)
return (T[]) Arrays.copyOf(a, antall, b.getClass());
System.arraycopy(a, 0, b, 0, antall);
if (b.length > antall) b[antall] = null;
return b;
}
@Override
public void forEach(Consumer<? super T> action)
{
for (int i = 0; i < antall; i++)
{
action.accept(a[i]);
}
}
@Override
public Iterator<T> iterator()
{
return new TabellListeIterator();
}
private class TabellListeIterator implements Iterator<T>
{
private int denne;
private boolean fjernOK;
private int iteratorendringer;
private TabellListeIterator()
{
denne = 0;
fjernOK = false;
iteratorendringer = endringer;
}
@Override
public boolean hasNext()
{
return denne < antall;
}
@Override
public T next()
{
if (iteratorendringer != endringer)
{
throw new ConcurrentModificationException("Listen er endret!");
}
if (!hasNext())
{
throw new NoSuchElementException("Tomt eller ingen verdier igjen!");
}
T denneverdi = a[denne];
denne++;
fjernOK = true;
return denneverdi;
}
@Override
public void forEachRemaining(Consumer<? super T> action)
{
while (denne < antall)
{
action.accept(a[denne++]);
}
}
@Override
public void remove()
{
if (iteratorendringer != endringer)
throw new ConcurrentModificationException("Listen er endret!");
if (!fjernOK)
throw new IllegalStateException("Ulovlig tilstand!");
fjernOK = false;
antall--;
denne--;
for (int i = denne; i < antall; i++) a[i] = a[i + 1];
a[antall] = null;
endringer++;
iteratorendringer++;
}
}
}