I want to know if there is any possibility that we can create a Java java.util.List which only allows the addition of element but doesn't allow the removal of elements?
One way I am thinking of overriding remove method. Please suggest.
This could be achieved using Decorator pattern. This way it could be applied to all container that implement List:
private static class UnremovableList<E> implements List<E> {
private List<E> innerContainer;
public UnremovableList(List<E> original) {
innerContainer = original
}
#Override
public void add(int location, E object) {
innerContainer.add(location, object);
}
#Override
public boolean add(E object) {
return innerContainer.add(object);
}
#Override
public boolean addAll(int location, Collection<? extends E> collection) {
return innerContainer.addAll(location, collection);
}
#Override
public boolean addAll(Collection<? extends E> collection) {
return innerContainer.addAll(collection);
} -
#Override
public void clear() {
throw new UnsupportedOperationException();
}
#Override
public boolean contains(Object object) {
return innerContainer.contains(object);
}
#Override
public boolean containsAll(Collection<?> collection) {
return innerContainer.containsAll(collection);
}
#Override
public E get(int location) {
return innerContainer.get(location);
}
#Override
public int indexOf(Object object) {
return innerContainer.indexOf(object);
}
#Override
public boolean isEmpty() {
return innerContainer.isEmpty();
}
#NonNull
#Override
public ListIterator<E> listIterator() {
return listIterator(0);
}
#NonNull
#Override
public Iterator<E> iterator() {
return new Iterator<E>() {
Iterator<E> iterator = innerContainer.iterator();
#Override public boolean hasNext() {
return iterator.hasNext();
}
#Override public E next() {
return iterator.next();
}
#Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
#Override
public ListIterator<E> listIterator(final int location) {
return new ListIterator<E>() {
ListIterator<E> iterator = innerContainer.listIterator(location);
#Override public void add(E object) {
throw new UnsupportedOperationException();
}
#Override public boolean hasNext() {
return iterator.hasNext();
}
#Override public boolean hasPrevious() {
return iterator.hasPrevious();
}
#Override public E next() {
return iterator.next();
}
#Override public int nextIndex() {
return iterator.nextIndex();
}
#Override public E previous() {
return iterator.previous();
}
#Override public int previousIndex() {
return iterator.previousIndex();
}
#Override public void remove() {
throw new UnsupportedOperationException();
}
#Override public void set(E object) {
throw new UnsupportedOperationException();
}
};
}
#Override
public int lastIndexOf(Object object) {
return innerContainer.lastIndexOf(object);
}
#Override
public E remove(int location) {
throw new UnsupportedOperationException();
}
#Override
public boolean remove(Object object) {
throw new UnsupportedOperationException();
}
#Override
public boolean removeAll(Collection<?> collection) {
throw new UnsupportedOperationException();
}
#Override
public boolean retainAll(Collection<?> collection) {
throw new UnsupportedOperationException();
}
#Override
public E set(int location, E object) {
return innerContainer.set(location, object);
}
#Override
public int size() {
return innerContainer.size();
}
#NonNull
#Override
public List<E> subList(int start, int end) {
return new UnremovableList(innerContainer.subList(start, end));
}
#NonNull
#Override
public Object[] toArray() {
return innerContainer.toArray();
}
#NonNull
#Override
public <T> T[] toArray(T[] array) {
return innerContainer.toArray(array);
}
}
Usage:
List<String> stableList = new UnremovableList(Arrays.asList("A", "B", "C"));
You can extend an existing List implementing class and override all public deleting methods, but it are quite a few methods to override (maybe even more, below are all I've found quickly)
public class UnDeletableList<E> extends ArrayList<E> {
#Override
public E remove(int index) {
throw new UnsupportedOperationException("don't remove from this list");
}
#Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("don't remove from this list");
}
#Override
public boolean removeAll(Collection<?> o) {
throw new UnsupportedOperationException("don't remove from this list");
}
#Override
public boolean retainAll(Collection<?> o) {
throw new UnsupportedOperationException("don't remove from this list");
}
#Override
public void clear() {
throw new UnsupportedOperationException("don't remove from this list");
}
// OPTIONAL IN CASE OF EXTRA STRICTNESS
#Override
public void replaceAll(UnaryOperator<E> u) {
throw new UnsupportedOperationException("don't remove from this list");
}
#Override
public E set(int i, E e) {
throw new UnsupportedOperationException("don't remove from this list");
}
}
Related
I am trying to sort the category arraylist with Collections.sort method but have no luck with it.
Here is my code:
public class Categories implements Parcelable {
private ArrayList<Category> category;
private Recent recent;
public ArrayList<Category> getCategories() {
return this.category;
}
public void setCategory(ArrayList<Category> category) {
this.category = category;
}
public Recent getRecent() {
return this.recent;
}
public void setRecent(Recent recent) {
this.recent = recent;
}
protected Categories(Parcel in) {
if (in.readByte() == 0x01) {
category = new ArrayList<Category>();
in.readList(category, Category.class.getClassLoader());
} else {
category = null;
}
recent = (Recent) in.readValue(Recent.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
if (category == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(category);
}
dest.writeValue(recent);
}
public static final Parcelable.Creator<Categories> CREATOR = new Parcelable.Creator<Categories>() {
#Override
public Categories createFromParcel(Parcel in) {
return new Categories(in);
}
#Override
public Categories[] newArray(int size) {
return new Categories[size];
}
};
}
You can also use custom comparator:
public class CategoriesComparator implements Comparator<Category> {
#Override
public int compare(Category category1, Category category2) {
return category1.getSomeProperty().compareTo(category2.getSomeProperty());
}
}
When you want to compare call this:
Collections.sort(yourListCategories, new CategoriesComparator());
Hope it helps!
Collections.sort(yourListHere,new Comparator<Categories>() {
#Override
public int compare(Categories lhs, Categories rhs) {
//your sort logic here
return 0;
}
});
Hope this helps.
Code below counts files with certain name. TypeCount is then some number (four for example).
File dir = new File(Environment.getExternalStorageDirectory().toString(), "/AppDir/" );
File[] files=dir.listFiles();
int typeCount = 0;
String type = "dog";
for (int i=0; i<files.length; i++) {
File file = files[i];
String filepath = file.getPath();
if(filepath.contains(type)){
typeCount = typeCount + 1;
}
}
In this code I want to put every path (File) in the List<File>. But when I set typeCount to size of the List I get always zero instead.
File dir = new File(Environment.getExternalStorageDirectory().toString(), "/AppDir/" );
File dir = new File(Environment.getExternalStorageDirectory().toString(), "/AppDir/" );
File[] files=dir.listFiles();
int typeCount = 0;
String typeype = "dog";
List<File> myList;
myList = new List<File>() {
#Override
public void add(int i, File file) {
}
#Override
public boolean add(File file) {
return false;
}
#Override
public boolean addAll(int i, Collection<? extends File> collection) {
return false;
}
#Override
public boolean addAll(Collection<? extends File> collection) {
return false;
}
#Override
public void clear() {
}
#Override
public boolean contains(Object o) {
return false;
}
#Override
public boolean containsAll(Collection<?> collection) {
return false;
}
#Override
public File get(int i) {
return null;
}
#Override
public int indexOf(Object o) {
return 0;
}
#Override
public boolean isEmpty() {
return false;
}
#NonNull
#Override
public Iterator<File> iterator() {
return null;
}
#Override
public int lastIndexOf(Object o) {
return 0;
}
#Override
public ListIterator<File> listIterator() {
return null;
}
#NonNull
#Override
public ListIterator<File> listIterator(int i) {
return null;
}
#Override
public File remove(int i) {
return null;
}
#Override
public boolean remove(Object o) {
return false;
}
#Override
public boolean removeAll(Collection<?> collection) {
return false;
}
#Override
public boolean retainAll(Collection<?> collection) {
return false;
}
#Override
public File set(int i, File file) {
return null;
}
#Override
public int size() {
return 0;
}
#NonNull
#Override
public List<File> subList(int i, int i1) {
return null;
}
#NonNull
#Override
public Object[] toArray() {
return new Object[0];
}
#NonNull
#Override
public <T> T[] toArray(T[] ts) {
return null;
}
};
for (int i=0; i<files.length; i++){
File file = files[i];
String filepath = file.getPath();
if(filepath.contains(type)){
myList.add(file);
}
}
typeCount = myList.size();
What is wrong here?
(And a little off topic - Is path written correctly? I'm not sure about it.)
This method size() will always print 0 because your own List implementation has a wrong returning statement:
#Override
public int size() {
return 0; // Oops!
}
Another thing too, you don't really insert anything in your List because of this:
#Override
public boolean add(File file) {
return false; // Hum...
}
Your methods aren't completed yet to execute the same tasks as a normal List. You better should use ArrayList<File> or List<File> which will have all the right methods and won't require hard work from you. Don't reinvent the wheel ;)
Finally, the path are right declared, but you should test if the files are presents in the folder before executing the code. Something as follows:
File[] files = dir.listFiles();
if (files.length > 0) {
// loop and add to a list
}
in my code i need a ConcurrentLinkedDeque but i want to bind this Deque biiderectional to a TableView in JavaFX or at least the size of the Deque to a PieChart, whats the common way to do something like this. Is there something like a ObservableConcurrentLinkedDeque i could use instead of the ConcurrentLinkedDeque and bind directly to a TableView?
There is no such implementation in the JavaFX library.
Note that it really doesn't make sense to implement a concurrent collection of any kind for use as a backing list for a TableView (or any other JavaFX node that is bound to its state). Once you use this as the backing data for a UI node, it can only be accessed from the JavaFX thread, so making it thread safe is redundant. So you are reduced to asking for an observable list that is also a Deque.
To do this, you could subclass ModifiableObservableListBase, delegating it to a LinkedList, and implement Deque, also delegating those methods to the LinkedList. You just need to be careful to fire changes when you call Deque methods that modify the list. So something like:
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import javafx.collections.ModifiableObservableListBase;
public class ObservableLinkedList<T> extends ModifiableObservableListBase<T> implements Deque<T> {
private final LinkedList<T> list = new LinkedList<>();
#Override
public void addFirst(T e) {
list.addFirst(e);
beginChange();
nextAdd(0, 1);
++modCount ;
endChange();
}
#Override
public void addLast(T e) {
list.addLast(e);
int size = list.size();
beginChange();
nextAdd(size-1, size);
++modCount ;
endChange();
}
#Override
public boolean offerFirst(T e) {
addFirst(e);
return true ;
}
#Override
public boolean offerLast(T e) {
addLast(e);
return true ;
}
#Override
public T removeFirst() {
T old = list.removeFirst() ;
beginChange();
nextRemove(0, old);
++modCount ;
endChange();
return old ;
}
#Override
public T removeLast() {
T old = list.removeLast() ;
beginChange();
nextRemove(list.size(), old);
++modCount ;
endChange();
return old ;
}
#Override
public T pollFirst() {
T result = list.pollFirst();
if (result != null) {
beginChange();
nextRemove(0, result);
++modCount ;
endChange();
}
return result ;
}
#Override
public T pollLast() {
T result = list.pollLast();
if (result != null) {
beginChange();
nextRemove(list.size(), result);
++modCount ;
endChange();
}
return result ;
}
#Override
public T getFirst() {
return list.getFirst() ;
}
#Override
public T getLast() {
return list.getLast() ;
}
#Override
public T peekFirst() {
return list.peekFirst() ;
}
#Override
public T peekLast() {
return list.peekLast() ;
}
#Override
public boolean removeFirstOccurrence(Object o) {
// not efficient: maybe a more efficient way, but we need the index...
int index = list.indexOf(o);
if (index > -1) {
remove(index);
return true ;
} else {
return false ;
}
}
#Override
public boolean removeLastOccurrence(Object o) {
// not efficient: maybe a more efficient way, but we need the index...
int index = list.lastIndexOf(o);
if (index > -1) {
remove(index);
return true ;
} else {
return false ;
}
}
#Override
public boolean offer(T e) {
return offerLast(e);
}
#Override
public T remove() {
return removeFirst();
}
#Override
public T poll() {
return pollFirst();
}
#Override
public T element() {
return getFirst();
}
#Override
public T peek() {
return peekFirst();
}
#Override
public void push(T e) {
addFirst(e);
}
#Override
public T pop() {
return removeFirst();
}
#Override
public Iterator<T> descendingIterator() {
return list.descendingIterator();
}
#Override
public T get(int index) {
return list.get(index);
}
#Override
public int size() {
return list.size();
}
#Override
protected void doAdd(int index, T element) {
list.add(index, element);
}
#Override
protected T doSet(int index, T element) {
return list.set(index, element);
}
#Override
protected T doRemove(int index) {
return list.remove(index);
}
}
Usage example:
ObservableLinkedList<String> list = new ObservableLinkedList<>();
list.addListener((Change<? extends String> c) -> {
while (c.next()) {
if (c.wasAdded()) {
System.out.println("Added from "+c.getFrom()+" to "+c.getTo()+" "+c.getAddedSubList());
}
if (c.wasRemoved()) {
System.out.println("Removed from "+c.getFrom() + " to "+c.getTo()+" "+c.getRemoved());
}
if (c.wasUpdated()) {
System.out.println("Updated");
}
if (c.wasPermutated()) {
System.out.println("Permutated");
}
}
});
list.addAll("Two", "Three", "Four");
list.offerFirst("One");
list.offer("Five");
System.out.println(list.pollFirst());
System.out.println(list.pollLast());
I have created three entity classes whose relation is defined as follows:
Screen -----> has many ConfigurableRows
ConfigurableRows -----> Has many Seats.
When i am trying to persist the Screen Class object no table is getting creating.
I am attaching my entity classes here.
public class Screen {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int screenid;
private String screenName;
#OneToMany(targetEntity=ConfigurableRow.class, mappedBy="screenid", fetch=FetchType.LAZY,cascade= CascadeType.ALL)
private List<ConfigurableRow> rows;
public Screen(){
rows = new ArrayList<ConfigurableRow>(10);
}
public Screen(int rowSize){
rows = new ArrayList<ConfigurableRow>(rowSize);
}
public String getScreenName() {
return screenName;
}
public void setScreenName(String screenName) {
this.screenName = screenName;
}
public int getScreenid() {
return screenid;
}
public void setScreenid(int screenid) {
this.screenid = screenid;
}
public List<ConfigurableRow> getRows() {
return rows;
}
public void setRows(List<ConfigurableRow> rows) {
this.rows = rows;
}
}
public class ConfigurableRow implements List<Seat>, IConfigureRow , IRow {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int rowId;
private int numberOfSeats;
private String rowName;
private String screenName;
private int screenid;
#ElementCollection
List<Seat> seats;
public ConfigurableRow(){
this.numberOfSeats = 10;
this.rowName = "Default";
this.screenName = "Default";
this.seats = new ArrayList<>(numberOfSeats);
}
public ConfigurableRow(int numberOfSeats,String screenName , String rowName){
this.numberOfSeats = numberOfSeats;
this.rowName = rowName;
this.screenName = screenName;
this.seats = new ArrayList<Seat>(numberOfSeats);
}
public int getRowId() {
return rowId;
}
#ManyToOne(targetEntity = Screen.class,fetch = FetchType.LAZY,cascade = CascadeType.ALL)
#JoinColumn (name="screenid",referencedColumnName="screenid",nullable=false,unique=false)
public int getScreenid() {
return screenid;
}
public void setScreenid(int screenid) {
this.screenid = screenid;
}
public List<Seat> getSeats() {
return seats;
}
public void setSeats(List<Seat> seats) {
this.seats = seats;
}
public String getRowName() {
return rowName;
}
public String getScreenName() {
return screenName;
}
#Override
public boolean add(Seat e) {
return seats.add(e);
}
#Override
public boolean addAll(Collection<? extends Seat> c) {
if(c.size() >= numberOfSeats){
throw new IllegalArgumentException("Seat Limit Exceeds!!!!!");
}
else {
return addAll(c);
}
}
#Override
public void clear() {
seats.clear();
}
#Override
public boolean contains(Object o) {
return seats.contains(o);
}
#Override
public boolean containsAll(Collection<?> c) {
return seats.containsAll(c);
}
#Override
public boolean isEmpty() {
return seats.isEmpty();
}
#Override
public Iterator<Seat> iterator() {
return seats.iterator();
}
#Override
public boolean remove(Object o) {
return seats.remove(o);
}
#Override
public boolean removeAll(Collection<?> c) {
return seats.removeAll(c);
}
#Override
public boolean retainAll(Collection<?> c) {
return seats.removeAll(c);
}
#Override
public int size() {
return seats.size();
}
#Override
public Object[] toArray() {
return seats.toArray();
}
#Override
public <T> T[] toArray(T[] a) {
return seats.toArray(a);
}
#Override
public boolean addSeat(Seat seat) {
if(seats.size() >= numberOfSeats){
throw new IllegalArgumentException("Seat Limit Exceeds!!!!!");
} else{
return add(seat);
}
}
#Override
public boolean addSeat(Seat seat, int seatNumber) {
if(seats.size() >= numberOfSeats){
throw new IllegalArgumentException("Seat Limit Exceeds!!!!!");
} else{
add(seatNumber,seat);
return true;
}
}
#Override
public boolean addAll(int index, Collection<? extends Seat> c) {
if(seats.size() + c.size() > numberOfSeats){
throw new IllegalArgumentException();
}
else {
return seats.addAll(index, c);
}
}
#Override
public Seat get(int index) {
return seats.get(index);
}
#Override
public Seat set(int index, Seat element) {
return seats.set(index, element);
}
#Override
public void add(int index, Seat element) {
seats.add(index, element);
}
#Override
public Seat remove(int index) {
return seats.remove(index);
}
#Override
public int indexOf(Object o) {
return seats.indexOf(o);
}
#Override
public int lastIndexOf(Object o) {
return seats.lastIndexOf(o);
}
#Override
public ListIterator<Seat> listIterator() {
return seats.listIterator();
}
#Override
public ListIterator<Seat> listIterator(int index) {
return seats.listIterator(index);
}
#Override
public List<Seat> subList(int fromIndex, int toIndex) {
return seats.subList(fromIndex, toIndex);
}
public int getNumberOfSeats() {
return numberOfSeats;
}
public void setNumberOfSeats(int numberOfSeats) {
this.numberOfSeats = numberOfSeats;
}
public List<Seat> getRowSet() {
return seats;
}
public void setRowSet(List<Seat> rowSet) {
this.seats = rowSet;
}
}
public class Seat implements Serializable {
/**
*
*/
private static final long serialVersionUID = 8083252956190536785L;
/*#Id #GeneratedValue(strategy=GenerationType.AUTO)
private int seatid;*/
private int seatNumber;
private SeatType seatType;
public int getSeatNumber() {
return seatNumber;
}
public void setSeatNumber(int seatNumber) {
this.seatNumber = seatNumber;
}
public SeatType getSeatType() {
return seatType;
}
public void setSeatType(SeatType seatType) {
this.seatType = seatType;
}
}
I am new to hibernate. Kindly let me know what I am doing wrong here.
My Tables are getting created now . But with out any values. Hence foreign key violation error is coming.
I think that is a OneToMany bidirectional relationship so
in the class ConfigurableRow you have to add an object from Screen class with annotation #ManyToOne
#ManyToOne
private Screen screen
i think you should put the onetomany annotation before your getrows() method.
#OneToMany(targetEntity=ConfigurableRow.class, mappedBy="screenid", fetch=FetchType.LAZY,cascade= CascadeType.ALL)
public List<ConfigurableRow> getRows() {
return rows;
}
I'm trying to create an implementation of TransformList that maintains a list of distinct values off a source list. However, I'm a little puzzled on how the implementation should add the distinct values to my hashmap and distinct list that are contained internally. I think my ListChangeListener.change should work though. But how do I intercept any new or removed distinct values and add/remove them to the distinct map and list?
public class DistinctList<E> extends TransformationList<E,E> {
private final ObservableList<E> distinctList = FXCollections.observableArrayList();
private final ConcurrentHashMap<E,E> distinctValues = new ConcurrentHashMap<>();
private final ObservableList<E> source;
public DistinctList(ObservableList<E> source) {
super(source);
this.source = source;
source.stream().filter(s -> attemptAdd(s)).forEach(s -> distinctList.add(s));
}
private boolean attemptAdd(E e) {
final boolean result = distinctValues.putIfAbsent(e,e) == null;
if (result) {
distinctList.add(e);
}
return result;
}
private boolean attemptRemove(E e) {
final boolean result = distinctValues.remove(e, e);
if (result) {
distinctList.remove(e);
}
return result;
}
#Override
protected void sourceChanged(ListChangeListener.Change<? extends E> c) {
fireChange(new ListChangeListener.Change<E>(this) {
#Override
public boolean wasAdded() {
if (c.getAddedSubList().stream().filter(v -> distinctValues.contains(v) == false).findAny().isPresent()) {
return true;
}
else {
return false;
}
}
#Override
public boolean wasRemoved() {
if (c.getRemoved().stream().filter(v -> !source.contains(v)).findAny().isPresent()) {
return true;
}
else {
return false;
}
}
#Override
public boolean wasPermutated() {
return false;
}
#Override
protected int[] getPermutation() {
throw new AssertionError("getPermutation() not implemented");
}
#Override
public List<E> getRemoved() {
return c.getRemoved().stream().filter(v -> !source.contains(v)).collect(Collectors.toList());
}
#Override
public int getFrom() {
return 0;
}
#Override
public int getTo() {
return 0;
}
#Override
public boolean next() {
return c.next();
}
#Override
public void reset() {
c.reset();
}
});
}
#Override
public int getSourceIndex(int index) {
return IntStream.range(0,source.size()).filter(i -> source.get(i).equals(this.get(i))).findAny().orElse(-1);
}
#Override
public E get(int index) {
return distinctList.get(index);
}
#Override
public int size() {
return distinctList.size();
}
}
UPDATE
I kept working with this and I think I figured out where to interact source changes with the distinct value map and list. But when my source list removes a value (and other values with same hashcode/equals still exists), it wrongly removes the value from the distinct values. What am I doing wrong?
public class DistinctList<E> extends TransformationList<E,E> {
private final ObservableList<E> distinctList = FXCollections.observableArrayList();
private final ConcurrentHashMap<E,E> distinctValues = new ConcurrentHashMap<>();
private final ObservableList<E> source;
public DistinctList(ObservableList<E> source) {
super(source);
this.source = source;
source.stream().forEach(s -> attemptAdd(s));
}
private boolean attemptAdd(E e) {
final boolean result = distinctValues.putIfAbsent(e,e) == null;
if (result) {
distinctList.add(e);
}
return result;
}
private boolean attemptRemove(E e) {
final boolean result = distinctValues.remove(e, e);
if (result) {
distinctList.remove(e);
}
return result;
}
#Override
protected void sourceChanged(ListChangeListener.Change<? extends E> c) {
ListChangeListener.Change<E> change = new ListChangeListener.Change<E>(this) {
#Override
public boolean wasAdded() {
if (c.getAddedSubList().stream().filter(v -> source.contains(v)).findAny().isPresent()) {
return true;
}
else {
return false;
}
}
#Override
public boolean wasRemoved() {
if (c.getRemoved().stream().filter(v -> source.contains(v) == false).findAny().isPresent()) {
return true;
}
else {
return false;
}
}
#Override
public boolean wasPermutated() {
return false;
}
#Override
protected int[] getPermutation() {
throw new AssertionError("getPermutation() not implemented");
}
#Override
public List<E> getRemoved() {
return c.getRemoved().stream().filter(v -> source.contains(v) == false)
.collect(Collectors.toList());
}
#Override
public int getFrom() {
return 0;
}
#Override
public int getTo() {
return 0;
}
#Override
public boolean next() {
return c.next();
}
#Override
public void reset() {
c.reset();
}
};
while (c.next()) {
if (c.wasAdded()) {
c.getAddedSubList().stream().filter(v -> !distinctValues.containsKey(v)).peek(a -> System.out.println("ADDING FROM MAP " + a)).forEach(a -> attemptAdd(a));
}
if (c.wasRemoved()) {
c.getRemoved().stream().filter(v -> distinctValues.containsKey(v)).peek(a -> System.out.println("REMOVING FROM MAP " + a)).forEach(a -> attemptRemove(a));
}
}
fireChange(change);
}
#Override
public int getSourceIndex(int index) {
return IntStream.range(0,source.size()).filter(i -> source.get(i).equals(this.get(i))).findAny().orElse(-1);
}
#Override
public E get(int index) {
return distinctList.get(index);
}
#Override
public int size() {
return distinctList.size();
}
}
I think I got it. Let me know if I'm missing anything.
public class DistinctList<E> extends TransformationList<E,E> {
private final ObservableList<E> distinctList = FXCollections.observableArrayList();
private final ConcurrentHashMap<E,E> distinctValues = new ConcurrentHashMap<>();
private final ObservableList<E> source;
public DistinctList(ObservableList<E> source) {
super(source);
this.source = source;
source.stream().forEach(s -> attemptAdd(s));
}
private boolean attemptAdd(E e) {
final boolean result = distinctValues.putIfAbsent(e,e) == null;
if (result) {
distinctList.add(e);
}
return result;
}
private boolean attemptRemove(E e) {
final boolean result = distinctValues.remove(e, e);
if (result) {
distinctList.remove(e);
}
return result;
}
#Override
protected void sourceChanged(ListChangeListener.Change<? extends E> c) {
while (c.next()) {
ListChangeListener.Change<E> change = new ListChangeListener.Change<E>(this) {
#Override
public boolean wasAdded() {
if (c.getAddedSubList().stream().filter(v -> distinctValues.contains(v) == false).findAny().isPresent()) {
return true;
} else {
return false;
}
}
#Override
public List<E> getAddedSubList() {
return c.getAddedSubList().stream().filter(v -> distinctValues.contains(v) == false).collect(Collectors.toList());
}
#Override
public boolean wasRemoved() {
if (c.getRemoved().stream().filter(v -> source.contains(v) == false).findAny().isPresent()) {
return true;
} else {
return false;
}
}
#Override
public boolean wasPermutated() {
return false;
}
#Override
protected int[] getPermutation() {
throw new AssertionError("getPermutation() not implemented");
}
#Override
public List<E> getRemoved() {
return c.getRemoved().stream().filter(v -> source.contains(v) == false)
.collect(Collectors.toList());
}
#Override
public int getFrom() {
return 0;
}
#Override
public int getTo() {
return 0;
}
#Override
public boolean next() {
return c.next();
}
#Override
public void reset() {
c.reset();
}
};
if (change.wasAdded()) {
change.getAddedSubList().stream().filter(v -> !distinctValues.containsKey(v)).peek(a -> System.out.println("ADDING FROM MAP " + a)).forEach(a -> attemptAdd(a));
}
if (change.wasRemoved()) {
change.getRemoved().stream().filter(v -> distinctValues.containsKey(v)).peek(a -> System.out.println("REMOVING FROM MAP " + a)).forEach(a -> attemptRemove(a));
}
fireChange(change);
}
}
#Override
public int getSourceIndex(int index) {
return IntStream.range(0,source.size()).filter(i -> source.get(i).equals(this.get(i))).findAny().orElse(-1);
}
#Override
public E get(int index) {
return distinctList.get(index);
}
#Override
public int size() {
return distinctList.size();
}
}