Strange bug with Streams - java

So I have created my own Set, which is just a regular set, but has additional functions (for example my set only stores absolute values).
Here is my Code:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet<E> extends HashSet<E> {
private Set<Integer> mySet;
public SortedByAbsoluteValueIntegerSet() {
mySet = new HashSet<Integer>();
}
#Override
public int size() {
return mySet.size();
}
#Override
public boolean add(E e){
return mySet.add(Math.abs((Integer) e));
}
#Override
public boolean remove(Object o) {
return mySet.remove(o);
}
#Override
public boolean contains(Object o){
return mySet.contains(o);
}
#Override
public boolean addAll(Collection<? extends E> c) {
List<Integer> myList = new ArrayList<>();
for (Object e: c) {
myList.add(Math.abs((Integer) e));
}
return mySet.addAll(myList);
}
#Override
public String toString(){
return mySet.toString();
}
}
I had a test case in JUnit, which failed. Because there was some issue with my code. For demonstration purpose, and for me to explain my issue better I have created two functions, which show the problem well.
Here is the problem:
public static void testSortedByAbsoluteValueIntegerSet() {
Set<Integer> set1 = new SortedByAbsoluteValueIntegerSet();
Set<Integer> set2 = new HashSet<>();
set1.add(5);
set1.add(3);
set2.add(5);
set2.add(3);
String x = toString(set1); //x is ""
String t = toString(set2); //t is "3 5"
}
public static String toString(final Collection<Integer> collection) {
return String.join(" ", collection.stream()
.map(i -> Integer.toString(i))
.toArray(String[]::new));
}
So the problem arises in this line:
String x = toString(set1); //x is always an empty string
String t = toString(set2); //t works correctly
When I go through debugger I see that String x is always an empty String and String t works correctly. By the way set1 is representation of my created set and set2 is just a regular hashset.
The question is: how can I fix my SortedByAbsoluteValueIntegerSet class so that the toString() method worked fine with my own created set as well.
P.S I am new to streams and I don't really understand the problem, why does it happens.

It's because you're extending HashSet but also using an internal Set.
When adding, you're adding to the internal Set but when using collection.stream() it calls the inherited HashSet (which is empty).
Easiest for you I beleive would be to remove the internal 'mySet' and call the inherited methods in your overridden methods.
For instance, your add method would be
#Override
public boolean add(E e){
return super.add(Math.abs((Integer) e));
}
(and then you don't need to override size, remove, contains of toString or spliterator)
Full example:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet extends HashSet<Integer> {
#Override
public boolean add(Integer e){
return super.add(Math.abs(e));
}
#Override
public boolean addAll(Collection<? extends Integer> c) {
List<Integer> myList = new ArrayList<>();
for (Integer e: c) {
myList.add(Math.abs(e));
}
return super.addAll(myList);
}
}

I think Tomas F gave better answer
Main problem in your set is using HashSet mySet as field and extending HashSet. In java better to use (field) composition instead of extending to add some functionality to your class. Here you tried use both - it's not a good idea.
Best decision is to use just composition and extending more general class, for example AbstractSet<Integer> and Set<Integer>:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet extends AbstractSet<Integer>
implements Set<Integer>, java.io.Serializable {
private final Set<Integer> mySet;
public SortedByAbsoluteValueIntegerSet() {
mySet = new HashSet<>();
}
#Override
public Iterator<Integer> iterator() {
return mySet.iterator();
}
#Override
public int size() {
return mySet.size();
}
#Override
public boolean add(Integer e) {
return mySet.add(Math.abs(e));
}
#Override
public boolean remove(Object o) {
return mySet.remove(o);
}
#Override
public boolean contains(Object o) {
return mySet.contains(o);
}
#Override
public boolean addAll(Collection<? extends Integer> c) {
List<Integer> myList = new ArrayList<>();
for (Integer e : c) {
myList.add(Math.abs(e));
}
return mySet.addAll(myList);
}
#Override
public String toString() {
return mySet.toString();
}
}
in this case you don't have to implement spliterator, because Set has default implementation using this keyword (which is refer to your set as a Collection)
but also you can implement spliterator in your class (but using such extends and internal Set fields are the bad practice. Also, it's better to get rid of type parameter E and casting elements to Integer:
import java.util.*;
public class SortedByAbsoluteValueIntegerSet extends HashSet<Integer> {
private Set<Integer> mySet;
public SortedByAbsoluteValueIntegerSet() {
mySet = new HashSet<>();
}
#Override
public int size() {
return mySet.size();
}
#Override
public boolean add(Integer e){
return mySet.add(Math.abs(e));
}
#Override
public boolean remove(Object o) {
return mySet.remove(o);
}
#Override
public boolean contains(Object o){
return mySet.contains(o);
}
#Override
public boolean addAll(Collection<? extends Integer> c) {
List<Integer> myList = new ArrayList<>();
for (Integer e: c) {
myList.add(Math.abs(e));
}
return mySet.addAll(myList);
}
#Override
public String toString(){
return mySet.toString();
}
#Override
public Spliterator<Integer> spliterator() {
return mySet.spliterator();
}
}

Related

Implementing a functional interface via method reference

First I got a class named after my Chinese name
public class Yxj<T> {
private T[] data;
private int size = 0;
private final Comparator<? super T> comparator;
public Yxj(Comparator<? super T> c) {
data= (T[]) new Object[16];
comparator = c;
}
public void addItem(T t){
data[size++] = t;
}
public int sort(){
return comparator.compare(data[0], data[1]);
}
public T[] getData(){
return data;
}
}
in which a Comparator resides,then I defined a Norwich keeping a field order and setter and getter of it, finally there's a method used to implement the compare(T t1,T t2) in Comparator.
public class Norwich {
private int order;
public Norwich(int o) {
order = o;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public int compareOrder(Norwich n) {
if (order > n.getOrder()) {
return 2;
} else if (order == n.getOrder()) {
return 0;
} else {
return -3;
}
}
}
then here comes the main method
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
norwichYxj.addItem(new Norwich(9));
norwichYxj.addItem(new Norwich(1));
System.out.println(norwichYxj.sort());
so what I'm interested in is that, why does not the method compareOrder keep the same parameters as the compare in Comparator but it can still work correctly?
It is simple. You have passed through the constructor your implementation of the Comparator to be used for comparing.
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
Remember Comparator is nothing else than an interface. Since it is a functional interface, it can be represented through a lambda expression or a
method reference (as you did). The way you can pass the Comparator in the full form is as follows. Note the usage of the compareOrder method:
Yxj<Norwich> norwichYxj = new Yxj<>(new Comparator<>() {
#Override
public int compare(Norwich o1, Norwich o2) {
return o1.compareOrder(o2); // usage of compareOrder
}
});
This can be shortened to a lambda expression:
Yxj<Norwich> norwichYxj = new Yxj<>((o1, o2) -> o1.compareOrder(o2));
It can be shortened again to a method reference:
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
Now you can see it can be represented in this way though the method compareOrder accepts only one formal parameter. The first parameter of the Comparator#compare method is the one invoking the compareOrder method and the second parameter is the one being passed to the compareOrder method.
Learn more here: https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
Additionally, the classes you have constructed look a bit odd. Though the other answer doesn't in fact answer your question, it can lead you to a better code: Implementing a functional interface via method reference
class Yxj
The paramter T of your class Yxj should have more restrictions if you want to compare/sort in this class with T then say T must be comparable.
If your T array grows then don't implement your own growing array but use ArrayList instead which does that for you
If you do the first you don't need the Comperator anymore
Your methode sort only sorts the first and second element so you will get problems. If the data is shorter you will get an ArrayIndexOutOfBoundsException if it is longer it won't sort the rest of elements. So with a Collection you could simple use Collections.sort(data);
public class Yxj<T extends Comparable<T>> {
private final List<T> data;
public Yxj() {
this.data = new ArrayList<>();
}
public void addItem(T t){
data.add(t);
}
public void sort(){
Collections.sort(data);
}
public List<T> getData(){
return data;
}
public void print(){
System.out.println(data);
}
}
class Norwich
If you done the above know your Norwich class must implement the Comparable interface so you can compare Norwich instances with the methode compareTo which also will be called each time you or the API ask directly or indirectly to compare to Norwich instances like for sorting ect.
public class Norwich implements Comparable<Norwich> {
private int order;
public Norwich(int o) {
this.order = o;
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
#Override
public int compareTo(Norwich other) {
return this.order - other.order;
}
#Override
public String toString() {
return "Norwich{" +
"order=" + order +
'}';
}
}
Main
Done? Perfect, then your main could be looks like this
public static void main(String[] args) {
Yxj<Norwich> norwichYxj = new Yxj<>();
norwichYxj.addItem(new Norwich(9));
norwichYxj.addItem(new Norwich(1));
norwichYxj.sort();
norwichYxj.print();
}

How to bypass Java not being able to extend from multiple classes

I think I have a design problem in my Java app, but I cannot figure out how to solve or bypass it.
Say I have an interface and an abstract class implementing it as follows:
public interface IntegerCollection extends Collection<Integer> {
public int sum();
}
public abstract class AbstractIntegerCollection
extends AbstractCollection<Integer> implements IntegerCollection {
public int sum() {
// fancy code to calculate the sum of all collection members (just an example)
}
}
Now I would want to make this class instantiable by using the existing implementations of Collection (e.g., LinkedList); something like this:
public class IntegerLinkedList extends AbstractIntegerCollection, LinkedList<Integer> {
}
IntegerCollection ic = new IntegerLinkedList();
However, this does not work because Java does not support extending several classes. Also it looks quite ugly to me, as there is a mixture of hierarchies.
Of course, I could let IntegerLinkedList implement IntegerCollection instead of letting it extend AbstractIntegerCollection. But then, I would have to repeat the code for sum() in all other implementations (e.g., IntegerArrayList).
Is there a better way to do this?
I'm not sure what exactly, you are trying to achieve, but rather you could implements List instead of extending LinkedList
public class IntegerLinkedList
extends AbstractIntegerCollection
implements List<Integer>
{
}
But, you need to implements all abstract method of List.
Since java 8 it has been possible to include implementations in an interface by using the default keyword. Therefore you don't need AbstractIntegerCollection - all the common code can be put in the interface. Here is an example:
import java.util.Collection;
import java.util.LinkedList;
public class Main {
interface IntegerCollection extends Collection<Integer> {
default int sum() {
int sum = 0;
for (int a : this)
sum += a;
return sum;
}
}
static class IntegerLinkedList extends LinkedList<Integer> implements IntegerCollection {
}
public static void main(String[] args) {
IntegerCollection list = new IntegerLinkedList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list.sum()); // Prints 6
}
}
This works, but I'm not sure it's a good idea. I'd think very carefully before extending a class like LinkedList. Some people also consider it an anti-pattern to extend generic classes with non-generic ones.
Another thing to be aware of is that it is not possible to write default methods for the methods of Object like equals and toString etc.
Since you are using Java 7, the above solution is not available. However, with a load of tedious forwarding methods, you can do it using composition rather than inheritance. Josh Bloch's book Effective Java gives a very good explanation of why composition is preferable anyway. Here is an (incomplete) example - you'll need to add a few more forwarding methods to avoid UnsupportedOperationExceptions when you try doing other things with the list.
import java.util.*;
public class Main {
abstract static class AbstractIntegerCollection extends AbstractCollection<Integer> {
public int sum() {
int sum = 0;
for (int a : this)
sum += a;
return sum;
}
}
static class IntegerLinkedList extends AbstractIntegerCollection implements List<Integer> {
private final List<Integer> list = new LinkedList<>();
#Override
public Iterator<Integer> iterator() {
return list.iterator();
}
#Override
public int size() {
return list.size();
}
#Override
public boolean addAll(int index, Collection<? extends Integer> c) {
return list.addAll(index, c);
}
#Override
public Integer get(int index) {
return list.get(index);
}
#Override
public Integer set(int index, Integer element) {
return list.set(index, element);
}
#Override
public boolean add(Integer element) {
return list.add(element);
}
#Override
public void add(int index, Integer element) {
list.add(index, element);
}
#Override
public Integer remove(int index) {
return list.remove(index);
}
#Override
public int indexOf(Object o) {
return list.indexOf(o);
}
#Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
#Override
public ListIterator<Integer> listIterator() {
return list.listIterator();
}
#Override
public ListIterator<Integer> listIterator(int index) {
return list.listIterator(index);
}
#Override
public List<Integer> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
// More of these
}
public static void main(String[] args) {
IntegerLinkedList list = new IntegerLinkedList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list.sum()); // Prints 6
}
}
This solution is far from perfect. For one thing, it would be better if IntegerLinkedList extended AbstractList<Integer> rather than just AbstractCollection<Integer>, but then you couldn't extend AbstractIntegerCollection too.

java generics - how to implement a class that takes a HashSet<T>?

Normally when you implement a generic, you have some type T that you want to generalize. I want to write a class that generalizes a HashSet<T>.
I'm trying to write this the following way, but it's not the correct syntax or maybe it's not supported:
public class PermutationHelper<T> implements Iterable<T> {
private HashSet<T> m_set;
private long numberOfPermutations;
private boolean includeEmptyPermutationAsOutput = false;
public PermutationHelper(HashSet<T> set) {
m_set = set;
numberOfPermutations = 2 ^ set.size();
}
public void setIncludeEmptyPermutationAsOutput(boolean value) {
includeEmptyPermutationAsOutput = value;
}
#Override
public Iterator<T> iterator() {
Iterator<T> it = new Iterator<T>() {
long currentIndex = (includeEmptyPermutationAsOutput ? 0 : 1);
#Override
public boolean hasNext() {
return currentIndex < numberOfPermutations;
}
#Override
public T next() {
HashSet<T> result = new HashSet<T>();
return result; // expects T, but is a HashSet<T>..
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
return it;
}
}
I want the Iterator to give me all subsets of the passed-in HashSet<T>.
You can easly do
public class PermutationHelper<T extends HashSet<T>> implements Iterable<T>
in order to 'force' the generic type to be an HashSet or a subtype of a HashSet
What you want is simply
public class PermutationHelper<T> implements Iterable<HashSet<T>>
Your class is generic. You choose to name its generic type T. And it implements Iterable<HashSet<T>>, which means it must have a method
public Iterator<HashSet<T>> iterator()

How is having a wrapper class equals composition as described Joshua Bloch?

I am reading the book effective java by Joshua Bloch. on the item 16 of "favor composition over inheritance", he gives an example of using HashSet and querying how many elements have been added since it was created(not to be confused with current size, which goes down when an element is removed). he provided the following code and here the getAddCount return 6, which I can understand. This should return 3 actually. (this is because HashSet's addAll method is implemented on top of its add method)
import java.util.HashSet;
public class InstrumentedHashSet<E> extends HashSet<E> {
// The number of attempted element insertions
private int addCount = 0;
public InstrumentedHashSet() {
}
public InstrumentedHashSet(int initCap, float loadFactor) {
super(initCap, loadFactor);
}
#Override
public boolean add(E e) {
addCount++;
return super.add(e);
}
#Override
public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c);
}
public int getAddCount() {
return addCount;
}
public static void main(String[] args) {
InstrumentedHashSet<String> s = new InstrumentedHashSet<String>();
s.addAll(Arrays.asList("Snap", "Crackle", "Pop"));
System.out.println(s.getAddCount());
}
}
Now he explains a way to fix this, using wrapper classes (composition and forwarding). here is where I am having hard time to understand. he provides the following two classes
public class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
public ForwardingSet(Set<E> s) {
this.s = s;
}
public void clear() {
s.clear();
}
public boolean contains(Object o) {
return s.contains(o);
}
public boolean isEmpty() {
return s.isEmpty();
}
public int size() {
return s.size();
}
public Iterator<E> iterator() {
return s.iterator();
}
public boolean add(E e) {
return s.add(e);
}
public boolean remove(Object o) {
return s.remove(o);
}
public boolean containsAll(Collection<?> c) {
return s.containsAll(c);
}
public boolean addAll(Collection<? extends E> c) {
return s.addAll(c);
}
public boolean removeAll(Collection<?> c) {
return s.removeAll(c);
}
public boolean retainAll(Collection<?> c) {
return s.retainAll(c);
}
public Object[] toArray() {
return s.toArray();
}
public <T> T[] toArray(T[] a) {
return s.toArray(a);
}
#Override
public boolean equals(Object o) {
return s.equals(o);
}
#Override
public int hashCode() {
return s.hashCode();
}
#Override
public String toString() {
return s.toString();
}
}
AND
import java.util.*;
public class InstrumentedSet<E> extends ForwardingSet<E> {
private int addCount = 0;
public InstrumentedSet(Set<E> s) {
super(s);
}
#Override
public boolean add(E e) {
addCount++;
return super.add(e);
}
#Override
public boolean addAll(Collection<? extends E> c) {
addCount += c.size();
return super.addAll(c);
}
public int getAddCount() {
return addCount;
}
public static void main(String[] args) {
InstrumentedSet<String> s = new InstrumentedSet<String>(
new HashSet<String>());
s.addAll(Arrays.asList("Snap", "Crackle", "Pop"));
System.out.println(s.getAddCount());
}
}
how this works? In the main method, I create an instance of HashSet and using addAll method, I add all the elements of list. but the HashSet invokes its addAll method (which in turn uses its add method), which should be the same as in the first in correct example and I should get value of 6, however this gives me 3.
In
public class InstrumentedHashSet<E> extends HashSet<E> {
you're adding directly to the HashSet because the addAll() is delegating to the super implementation
InstrumentedHashSet<String> s = new InstrumentedHashSet<String>();
s.addAll(Arrays.asList("Snap", "Crackle", "Pop"));
System.out.println(s.getAddCount());
The addAll() internally calls add() which defers to your #Override implementation of add() because of polymorphism
#Override
public boolean add(E e) {
addCount++;
return super.add(e);
}
that increments the count and prints 6 (3 + 1 + 1 + 1).
In
public class InstrumentedSet<E> extends ForwardingSet<E> {
you are adding to
private final Set<E> s;
because the addAll() is delegating to it, so
public static void main(String[] args) {
InstrumentedSet<String> s = new InstrumentedSet<String>(
new HashSet<String>());
s.addAll(Arrays.asList("Snap", "Crackle", "Pop"));
System.out.println(s.getAddCount());
}
and prints 3. Here the add() is being called on the Set<E> s, not on your instance.
The conclusion is that if you are inheriting, you need to understand the side-effects. Do the super method calls invoke any other method calls internally? If so, you need to act appropriately.
Inheritance (start from bottom)
s.add() // s is your InstrumentedHashSet instance, because of polymorphism (inheritance), this adds to the count
this.add() // this is the internal call inside the HashSet#addAll()
super.addAll(...) // this calls the HashSet implementation of addAll which calls add() internally
s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); // s is your InstrumentedHashSet instance
Composition
this.add() // this is the internal call to add() inside the Set implementation
s.addAll() // s is the Set<E> instance
super.addAll(...) // this calls the ForwardingSet implementation of addAll()
s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); // s is your InstrumentedSet instance
InstrumentedSet#getAddCount() returns 6 because the size of the array (3) is added twice!
//InstrumentedSet
public boolean addAll(Collection<? extends E> c) {
addCount += c.size(); //here
return super.addAll(c); //and here!
}
super.addAll(c); calls the add() Method.
More detailed:
InstrumentedSet#addAll -> ForwardingSet#addAll (because of super.addAll) -> HashSet#addAll() (because this is what you give it in the main) -> InstrumentedSet#add (because of polymorphism)
If you want a fix: remove addCount += c.size();
InstrumentedSet#addAll returns 3 because it calls this:
InstrumentedSet#addAll() (adds 3) -> ForwardingSet#addAll (because of super) -> HashSet#addAll (because forwardingset has a field of type HashSet) -> HashSet#add

How to add listener on ArrayList in java

I want to create my own implementation of ArrayList in java, that can listen when the list is changing and to do action when this happens.
From what I have read, I understand that I can't extend ArrayList and then add listener.
I want to use MyList in class as a variable with public modifier, so users can change it directly and to be done action when he changes it.
class MyList extends ArrayList<object>.... { ... }
class UseOfMyList {
public MyList places = new MyList<Object>();
places.add("Buenos Aires");
//and to be able to do that
List cities = new ArrayList<Object>();
cities.add("Belmopan");
places = cities;
So how to create and when do add,remove or pass another list to MyList an action to be performed?
You're not going to be able to do this by extending ArrayList, as it has no built-in notification mechanism (and, further, because it is has been declared final and thus cannot be extended). However, you can achieve your desired result by creating your own List implementation and adding your "listener" functionality vis a vis the add() and remove() methods:
class MyList<T>{
private ArrayList<T> list;
public MyList(){
list = new ArrayList<>();
...
}
public void add(T t){
list.add(t)
//do other things you want to do when items are added
}
public T remove(T t){
list.remove(t);
//do other things you want to do when items are removed
}
}
Old question, I know.
I apologize in advance for any bad formatting or missing lines of code. I'm a long-time user, first time contributor.
Anyhow, because of the removal of JavaFX from the JDK11, I was forced to write my own version of the ObservableList. Sure, we can plop JavaFX in with JMods or Maven, but it seems like a bit of an overkill just for the FXCollections.
Long Story made Short...er :)
I started out reading this old question and the answer didn't suit my needs fully, so I've added a custom event/listener class.
Figured I could share since this site has improved my coding 10 fold.
public static void main(String[] args) {
BackedList<String> list = new BackedList();
list.addListener(new BackedListListener<String>(){
#Override
public void setOnChanged(ListChangeEvent<String> event) {
if (event.wasAdded()) {
event.getChangeList().forEach(e->{
// do whatever you need to do
System.out.println("added: " + e);
});
}
if (event.wasRemoved()) {
// do whatever you need to dl
event.getChangeList().forEach(e->{System.out.println(e + " was removed");});
}
}
});
Class: BackedObservableList
public class BackedObservableList<T> implements List<T> {
private final List<T> backed;
public BackedObservableList() {
backed = new ArrayList();
}
public BackedObservableList(List<T> backed) {
this.backed = backed;
}
/*
You will want to override every method. For any method that performs an add/remove
operation, you will have to do some coding / testing. I'll do an add() op, a remove()
op, and an interator in this example. Anything that is not an add/remove op, you can straight up delegate it to the underlying list.
Also remember that list.clear() is a removal operation, where you can simply iterate through the backed list and call the overide remove(T t) method, or just plop the whole backed list into the ListChangeEvent<T> class and delegate to the backed array again.
*/
#Override
public boolean add(T e) {
if (backed.add(e)) {
ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(e), backed.indexOf(e) + 1, true, e);
notifyListeners(event);
return true;
}
return false;
}
}
#Override
public boolean remove(Object o) {
if (backed.remove(o)) {
ListChangeEvent<T> event = new ListChangeEvent(this, backed.indexOf(o),
backed.indexOf(o) + 1, false, o);
notifyListeners(event);
return true;
}
return false;
}
/*
The iterator seemed easy enough, until I remembered the iterator.remove() call.
I still haven't fully tested it (it works, but only as far as I've used it)
*/
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
T currentItem = null;
int currentIndex = 0;
#Override
public boolean hasNext() {
return backed.size() > currentIndex;
}
#Override
public T next() {
return currentItem = backed.get(currentIndex++);
}
#Override
public void remove() {
if (backed.remove(currentItem)) {
currentIndex--;
notifyListeners(new ListChangeEvent<T>(backed, currentIndex, currentIndex + 1, false, currentItem));
}
}
};
}
private void notifyListeners(ListChangeEvent<T> event) {
for (BackedListListener<T> listener : listeners) {
listener.setOnChanged(event);
}
}
private final List<BackedListListener> listeners = new ArrayList();
public void addListener(BackedListListener<T> listener) {
listeners.add(listener);
}
Class: ListChangeEvent
It simply provides a reference to the backed list (which you may want to wrap with Collections.unmodifiableList()
public class ListChangeEvent<T> {
private final List<T> source;
private final List<T> changeList;
private final boolean wasAdded;
private final int to, from;
public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, T... changeItems) {
this(source, from, to, wasAdded, Arrays.asList(changeItems));
}
public ListChangeEvent(List<T> source, int from, int to, boolean wasAdded, List<T> changeItems) {
this.source = source;
this.changeList = changeItems;
this.wasAdded = wasAdded;
this.to = to;
this.from = from;
}
public int getFrom() {
return from;
}
public int getTo() {
return to;
}
public List<T> getSource() {
return source;
}
public List<T> getChangeList() {
return changeList;
}
public boolean wasAdded() {
return wasAdded;
}
public boolean wasRemoved() {
return !wasAdded;
}
}
Class: BackedListListener
/*
Finally a little functional interface... or, because I was too lazy to change it to one, a simple one-liner abstract class with some generics
*/
public abstract class BackedListListener<T> {
public abstract void setOnChanged(ListChangeEvent<T> event);
}
the resp. ;)
private class MyList extends ArrayList<Objects> {
#Override
public void sort(Comparator c) {
super.sort(c);
resetLancamentos(); // call some metod ;)
}
//...
#Override
public boolean removeAll(Collection c) {
//To change body of generated methods, choose Tools | Templates.
boolean ret = super.removeAll(c);
resetLancamentos(); // some metod like fireObjChanged() will do the job too
return ret;
}
}

Categories

Resources