ObservableList listeners can receive Change events with permutation set.
Simultaneously, among list operations, I see only ones to delete or insert elements.
Is it possible to perform such operation on list, which will cause permutation reported?
UPDATE
Here is the clarification code:
public class ObservableListPermutation {
public static void main(String[] args) {
ObservableList<String> list = FXCollections.observableArrayList();
list.add("timbuktu");
list.add("timid");
list.addListener(new ListChangeListener<String>() {
#Override
public void onChanged(Change<? extends String> c) {
while(c.next()) {
if( c.wasPermutated() ) {
System.out.println("Was permutated");
}
}
}
});
System.out.println("Sorting by library:");
Collections.sort(list);
System.out.println("Sorting by own:");
Collections2.sort(list);
}
public static class Collections2 {
public static void sort(List<String> list) {
String element = list.remove(0);
list.add(element);
}
}
}
As you see, my custom permutation does not cause permutation event, because it is done by removing and adding elements. How to implement custom permutation, so that it cause permutation event?
UPDATE 2
If I try to trace sort() with debugger, I am unable to enter the code of sort().
To elaborate on #ItachiUchiha's answer and #fabian's comment, any single operation that modifies an ObservableList will notify change listeners. So there is no way to trigger a "permutation event" on an ObservableList by calling a sequence of operations that each modify the list (each operation would notify listeners independently).
So to support permutations that are not supported out of the box (i.e. by FXCollections.sort(), FXCollections.shuffle(), FXCollections.rotate(), and FXCollections.reverse()), you need to implement your own ObservableList, defining (or possibly overriding) single entry-point methods that trigger a permutation. The ModifiableObservableListBase class provides a convenient starting point.
Here is a simple example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.collections.ModifiableObservableListBase;
public class PermutatingObservableList<E> extends ModifiableObservableListBase<E> {
private final List<E> source ;
public PermutatingObservableList(List<E> source) {
this.source = source ;
}
public void permute(int[] permutation) {
checkPermutation(permutation);
beginChange();
List<E> temp = new ArrayList<>(source);
for (int i = 0 ; i < size() ; i++) {
source.set(i, temp.get(permutation[i]));
}
nextPermutation(0, size(), permutation);
endChange();
}
public void pairwiseSwap() {
int[] permutation = new int[size()];
for (int i = 0; i+1 < permutation.length ; i+=2) {
permutation[i] = i+1 ;
permutation[i+1] = i ;
}
if (permutation.length % 2 == 1) {
permutation[permutation.length - 1] = permutation.length - 1 ;
}
permute(permutation);
}
private void checkPermutation(int[] permutation) {
boolean valid = permutation.length == size();
Set<Integer> values = IntStream.range(0, size()).boxed().collect(Collectors.toSet());
for (int i=0; i<permutation.length && valid ; i++) {
valid = values.remove(new Integer(permutation[i]));
}
if (! valid) {
throw new IllegalArgumentException("Invalid permuation: "+Arrays.toString(permutation)+"\n"
+"Permutation must be same length as list and must contain each of the values "
+ "0-"+(size()-1)+" exactly once");
}
}
#Override
public E get(int index) {
return source.get(index);
}
#Override
public int size() {
return source.size();
}
#Override
protected void doAdd(int index, E element) {
source.add(index, element);
}
#Override
protected E doSet(int index, E element) {
return source.set(index, element);
}
#Override
protected E doRemove(int index) {
return source.remove(index);
}
}
and a test:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.collections.ListChangeListener;
public class PermutingObservableListTest {
public static void main(String[] args) {
List<String> numbers = Arrays.asList("One", "Two", "Three", "Four", "Five");
PermutatingObservableList<String> list = new PermutatingObservableList<>(new ArrayList<>(numbers));
list.addListener(new ListChangeListener<String>() {
#Override
public void onChanged(Change<? extends String> c) {
while (c.next())
System.out.println(c.wasPermutated());
System.out.println(IntStream.range(0, list.size())
.map(c::getPermutation)
.mapToObj(Integer::toString)
.collect(Collectors.joining(", ")));
}
}
});
list.pairwiseSwap();
System.out.println(list);
}
}
which produces the output
true
1, 0, 3, 2, 4
[Two, One, Four, Three, Five]
A very simple operation a List to report Permutation would be to sort the items in the List.
For example, the following code would print true.
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.Collections;
public class PermutationTest {
public static void main(String[] args) {
ObservableList<String> list =
FXCollections.observableArrayList("Z", "Y", "X");
list.addListener(new ListChangeListener<String>() {
#Override
public void onChanged(Change<? extends String> c) {
c.next();
System.out.println(c.wasPermutated());
}
});
Collections.sort(list);
}
}
Answers to additional question :
I would like to cause it myself, without calling black box methods. Suppose I have instance of ObservableList and nothing more and would like to code some manipulation, which causes permutation, How would I do this?
This is not possible if you are using the ObservableList provided by FXCollections util class because of the way ObservableList is implemented in it.
Considering the following points :
Whenever you add or remove elements a MappingChange is triggered.
ListChangeListener#wasPermutated() checks if length of the int array returned by getPermutation() is greater than zero.
In case of MappingChange, the getPermuatation() always returns an int of length 0.
Now, you must be wondering (like I was), how does it work when we do a sort on the same List?
It turns out the ObservableListWrapper (which is the base for creating list in FXCollections) overrides sort() and then forces a SimplePermutationChange.
Is there an alternative?
You can create your own custom ObservableList by extending ModifiableObservableListBase as stated by this comment and shown in this answer.
Related
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PowerSet {
public static final <E> Collection<Set<E>> of(Set<E> s) {
List<E> src = new ArrayList<>(s);
if (src.size() > 30) {
throw new IllegalArgumentException("Set too big " + s);
}
return new AbstractList<Set<E>>() {
#Override
public int size() {
return 1 << src.size(); // 2 to the power srcSize
}
#Override
public boolean contains(Object o) {
return o instanceof Set && src.containsAll((Set) o);
}
#Override
public Set<E> get(int index) {
Set<E> result = new HashSet<>();
for (int i = 0; index != 0; i++, index >>= 1) {
if ((index & 1) == 1) {
result.add(src.get(i));
}
}
return result;
}
};
}
public static void main(String[] args) {
Collection<Set<String>> set = new HashSet<>();
set.add()... }
I have this code I got from Java Effective as how implement
power set but I am confused how to initialise this set and
fill it with values. There is interface with three overridden
methods, concretely contains, get and size. What does of in class
declaration mean?
To initialize PowerSet instance you need to call it's constructor PowerSet(), though it'll be useless since there is no object related underlying logic in it.
"of" is a static method declared in PowerSet, accepting a set with size <= 30 and returning a List of Sets with logic of power set.
It is implemented by extension of AbstractList.
Set<Long> input = new HashSet<Long>();
input.add(1L);
input.add(2L);
List<Set<Long>> example = PowerSet.<Long>of(input);
So, example.get(0) will result with an empty HashSet, example.get(1) == {1}; example.get(2) == {2}, example.get(3) == {1, 2}
You can rewrite it in a more conventional format:
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PowerSet<E> extends AbstractList<Set<E>> {
private List<E> src;
public PowerSet(Set<E> s){
//copying set contains to a list to access by index
src = new ArrayList<>(s);
}
#Override
public int size() {
return 1 << src.size(); // 2 to the power srcSize
}
#Override
public boolean contains(Object o) {
return o instanceof Set && src.containsAll((Set) o);
}
#Override
public Set<E> get(int index) {
Set<E> result = new HashSet<>();
for (int i = 0; index != 0; i++, index >>= 1) {
if ((index & 1) == 1) {
result.add(src.get(i));
}
}
return result;
}
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add()...
PowerSet<String> = new PowerSet(set);
}
I'm very new to iterators but for an assignment I wrote a custom Iterator and I want to simply print out object as I iterate through a list of them but it keeps printing nothing and I have no idea why.
Here's the custom iterator code:
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
public class MyList<T> implements Iterable<T> {
private List<T> list;
private class MyIterator<t> implements Iterator<t> {
int lSize = list.size();
int lPoint = 0;
public boolean hasNext() {
return (lPoint < lSize);
}
public t next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
t val = (t) list.get(lPoint);
lPoint++;
return val;
}
}
public MyList(List<T> list) {
this.list = list;
}
public Iterator<T> iterator() {
return new MyIterator<>();
}
}
Here's the class I'm using to test it:
Public class TestCloning {
Electronics test = new Electronics("Test", 100, 10);
Electronics test3 = new Electronics("Test2", 300, 30);
List<Electronics> order1 = new ArrayList<>();
MyList<Electronics> mList1 = new MyList<>(order1);
Iterator<Electronics> mIterator1 = mList1.iterator();
public void testIterator(){
order1.add(test);
order1.add(test3);
while (mIterator1.hasNext()){
System.out.println(mIterator1.next().toString());
}
}
}
This is mainly because the lSize=0
The reason why it is zero is because you add the list of things to myList before you actually add any items into that list.
List<String> order1 = new ArrayList<>();
order1.add(test);
order1.add(test3);
MyList<String> mList1 = new MyList<>(order1);
Iterator<String> mIterator1 = mList1.iterator();
If you flip the order, add things to the order list, then create your custom one everything will work as you'd expect.
Also, I suggest in the future, don't use any custom iterators or lists that wrap normal lists. I understand this is for the purpose of an assignment, and then acceptable
I've been trying to find possible answers, but found none.
I've got an ArrayList full of custom objects. One of their fields is a boolean.
I want to put this object first, keeping the rest of elements
For instance, if I've got this list and obj5 is the one with this boolean set to true:
obj3, obj2, obj5, obj7, obj9
I'd like to get this:
obj5, obj3, obj2, obj7, obj9
EDIT: CAN'T USE LAMBDAS, JAVA 6
EDIT 2: PLEASE NOTE THAT THE REST OF THE LIST MUST KEEP THE OLD ORDER
EDIT 3: In short words, I need this program to output [B, A, C, D, E]:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Trip {
#Override
public String toString() {
return name;
}
private String name;
private boolean freeCancellation;
public Trip(String name, boolean freeCancellation) {
this.name = name;
this.freeCancellation = freeCancellation;
}
static Comparator<Trip> myOrder = new Comparator<Trip>() {
public int compare(Trip a, Trip b) {
if (a.freeCancellation == b.freeCancellation) return 0;
return a.freeCancellation ? -1 : 1;
}
};
public static void main(String [] args){
Trip t1 = new Trip("A", false);
Trip t2 = new Trip("B", true);
Trip t3 = new Trip("C", false);
Trip t4 = new Trip("D", true);
Trip t5 = new Trip("E", false);
List<Trip> tripList = new ArrayList<>();
tripList.add(t1);
tripList.add(t2);
tripList.add(t3);
tripList.add(t4);
tripList.add(t5);
System.out.println(Arrays.toString(tripList.toArray()));
Collections.sort(tripList, myOrder);
//result should be [B, A, C, D, E]
System.out.println(Arrays.toString(tripList.toArray()));
}
}
Write a Comparator.
Comparator<MyType> myOrder = new Comparator<MyType>() {
public int compare(MyType a, MyType b) {
return (b.booleanField() ? 1 : 0) - (a.booleanField() ? 1 : 0);
}
}
Sort using this comparator.
Collections.sort(myList, myOrder);
See Collections.sort
Edit
So it seems that what you're actually asking for is to move just one matching element to the front of your list. That ought to be pretty easy.
Find the index of the element you want to move:
int foundIndex = -1;
for (int i = 0; i < tripList.size(); ++i) {
if (tripList.get(i).freeCancellation) {
foundIndex = i;
break;
}
}
If you find such an element, and it is not already at the start, move it to the start:
if (foundIndex > 0) {
tripList.add(0, tripList.remove(foundIndex));
}
List<Object> objList = findObj(name);Collections.sort(objList, new Comparator<Object>() {
#Override
public int compare(Object a1, Object a2) {
return (a1.getBooleanField()== a2.getBooleanField())?0:(a1.getBooleanField()?1:-1);
}});
This might help you to resolve this. You modify the results by changing the compare logic
Here is an example of how to achieve this:
class Element {
public boolean shouldBeFirst();
}
List<Element> elements;
elements.sort(Comparator.comparing(Element::shouldBeFirst));
This works because the natural ordering of booleans is true first.
If you can't use Java 8 then the equivalent would be something like:
Collections.sort(elements, new Comparator() {
int compareTo(Element el1, Element el2) {
return (el1.shouldBeFirst() ? 1 : 0) - (el2.shouldBeFirst() ? 1 : 0);
}
}
import java.util.*;
public class Test {
public static void main(String[] args) {
List<A> list = new ArrayList<A>();
list.add(new A(true));
list.add(new A(false));
list.add(new A(true));
list.add(new A(false));
Collections.sort(list);
System.out.println(list);
}
}
class A implements Comparable<A> {
private boolean b;
public A(boolean b) {
this.b = b;
}
public boolean isB() {
return b;
}
public void setB(boolean b) {
this.b = b;
}
#Override
public int compareTo(A a) {
return a.isB() ? 1 : -1;
}
#Override
public String toString() {
return "A [b=" + b + "]";
}
}
Maybe this is what you are looking for.
This is solution if you want to give natural ordering to object, then implement Comparable and use Collections.sort - https://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List).
If you have various members inside class, then maybe go with Comparator implementation, that way you can achieve many ways of sorting your objects based on different members.
If I understood what are you asking ,you need to create a new class called "Comparators".
in this class you need to define your methods and they need to be static final ...
then you can use it by calling to Collections.sort(-your array-, Comparator method name);
I am trying to reverse an unmodifiable list. However i have tried to achieve it but Is it possible to update or reverse and unmodifiable list? I know we can do it with Google Immutable List
import java.util.*;
public class ImmutableList
{
public static void main(String args[])
{
String[] mylist = {"Apple","Orange","Mango","Kiwi","Banana"};
List reverselist = new ArrayList();
List<String> strList = Arrays.asList(mylist);
List<String> unmodifiableList = Collections.unmodifiableList(strList);
for(int i=unmodifiableList.size();i>0;i--)
{
reverselist.add(unmodifiableList.get(i-1));
}
List<String> reverse = Collections.unmodifiableList(reverselist);
System.out.println(reverse);
}
}
In the above program I am just traversing in unmodifable list from back and putting them in an array after that adding that array to new unmodifiable list. Can we do it in better way in terms of optimisation?
Guava's Lists.reverse(List) returns a reversed view of the original list, without doing any copying.
When the list is unmodifiable anyhow, you can just create a reversed view on the list.
This is optimal in terms of performance and storage: It requires O(1) time and O(1) additional space to create this list.
import java.util.AbstractList;
import java.util.Arrays;
import java.util.List;
public class ReversedListViewTest
{
public static void main(String[] args)
{
String[] array = {"Apple","Orange","Mango","Kiwi","Banana"};
List<String> list = Arrays.asList(array);
System.out.println("List : "+list);
List<String> reversedView = reversedView(list);
System.out.println("Reversed view: "+reversedView);
}
private static <T> List<T> reversedView(final List<T> list)
{
return new AbstractList<T>()
{
#Override
public T get(int index)
{
return list.get(list.size()-1-index);
}
#Override
public int size()
{
return list.size();
}
};
}
}
May be not the best solution but better then reverse ourself:
public List<T> reverseUnModList(List<T> unModListOrig) {
List<T> tmpList = new ArrayList<T>(unModListOrig);
Collections.reverse(tmpList);
return Collections.unmodifiableList(unModListOrig);
//return tmpList; //if the result not need to be unmodifieable
}
Is it possible to merge iterators in Java? I have two iterators and I want to combine/merge them so that I could iterate though their elements in one go (in same loop) rather than two steps. Is that possible?
Note that the number of elements in the two lists can be different therefore one loop over both lists is not the solution.
Iterator<User> pUsers = userService.getPrimaryUsersInGroup(group.getId());
Iterator<User> sUsers = userService.getSecondaryUsersInGroup(group.getId());
while(pUsers.hasNext()) {
User user = pUsers.next();
.....
}
while(sUsers.hasNext()) {
User user = sUsers.next();
.....
}
Guava (formerly Google Collections) has Iterators.concat.
Also the Apache Commons Collection have several classes for manipulating Iterators, like the IteratorChain, that wraps a number of Iterators.
You could create your own implementation of the Iterator interface which iterates over the iterators:
public class IteratorOfIterators implements Iterator {
private final List<Iterator> iterators;
public IteratorOfIterators(List<Iterator> iterators) {
this.iterators = iterators;
}
public IteratorOfIterators(Iterator... iterators) {
this.iterators = Arrays.asList(iterators);
}
public boolean hasNext() { /* implementation */ }
public Object next() { /* implementation */ }
public void remove() { /* implementation */ }
}
(I've not added generics to the Iterator for brevity.) The implementation is not too hard, but isn't the most trivial, you need to keep track of which Iterator you are currently iterating over, and calling next() you'll need to iterate as far as you can through the iterators until you find a hasNext() that returns true, or you may hit the end of the last iterator.
I'm not aware of any implementation that already exists for this.
Update:
I've up-voted Andrew Duffy's answer - no need to re-invent the wheel. I really need to look into Guava in more depth.
I've added another constructor for a variable number of arguments - almost getting off topic, as how the class is constructed here isn't really of interest, just the concept of how it works.
I haven't written Java code in a while, and this got me curious to whether I've still "got it".
First try:
import java.util.Iterator;
import java.util.Arrays; /* For sample code */
public class IteratorIterator<T> implements Iterator<T> {
private final Iterator<T> is[];
private int current;
public IteratorIterator(Iterator<T>... iterators)
{
is = iterators;
current = 0;
}
public boolean hasNext() {
while ( current < is.length && !is[current].hasNext() )
current++;
return current < is.length;
}
public T next() {
while ( current < is.length && !is[current].hasNext() )
current++;
return is[current].next();
}
public void remove() { /* not implemented */ }
/* Sample use */
public static void main(String... args)
{
Iterator<Integer> a = Arrays.asList(1,2,3,4).iterator();
Iterator<Integer> b = Arrays.asList(10,11,12).iterator();
Iterator<Integer> c = Arrays.asList(99, 98, 97).iterator();
Iterator<Integer> ii = new IteratorIterator<Integer>(a,b,c);
while ( ii.hasNext() )
System.out.println(ii.next());
}
}
You could of course use more Collection classes rather than a pure array + index counter, but this actually feels a bit cleaner than the alternative. Or am I just biased from writing mostly C these days?
Anyway, there you go. The answer to you question is "yes, probably".
public class IteratorJoin<T> implements Iterator<T> {
private final Iterator<T> first, next;
public IteratorJoin(Iterator<T> first, Iterator<T> next) {
this.first = first;
this.next = next;
}
#Override
public boolean hasNext() {
return first.hasNext() || next.hasNext();
}
#Override
public T next() {
if (first.hasNext())
return first.next();
return next.next();
}
}
Starting with Java 8 and later this can be done without external dependencies using Stream API. This also allows concatenation of iterator with other types of streams.
Streams.concat(StreamSupport.stream(<iter1>, false), StreamSupport.stream(<iter2>, false));
move your loop to a method and pass the iterator to method.
void methodX(Iterator x) {
while (x.hasNext()) {
....
}
}
an iterator comes FROM a collection or a set.
why not use the method already available
Collection.addAll(Collection c);
and then create your iterator from the last object.
this way, your iterator will iterate all the contents of both collection.
You can use my version of an extendable iterator. It uses a double-ended queue of iterators which to me makes sense:
import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedDeque;
public class ExtendableIterator<T> implements Iterator<T> {
public Deque<Iterator<T>> its = new ConcurrentLinkedDeque<Iterator<T>>();
public ExtendableIterator() {
}
public ExtendableIterator(Iterator<T> it) {
this();
this.extend(it);
}
#Override
public boolean hasNext() {
// this is true since we never hold empty iterators
return !its.isEmpty() && its.peekLast().hasNext();
}
#Override
public T next() {
T next = its.peekFirst().next();
if (!its.peekFirst().hasNext()) {
its.removeFirst();
}
return next;
}
public void extend(Iterator<T> it) {
if (it.hasNext()) {
its.addLast(it);
}
}
}
The Merged Iterator:
import static java.util.Arrays.asList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
public class ConcatIterator<T> implements Iterator<T> {
private final List<Iterable<T>> iterables;
private Iterator<T> current;
#SafeVarargs
public ConcatIterator(final Iterable<T>... iterables) {
this.iterables = new LinkedList<>(asList(iterables));
}
#Override
public boolean hasNext() {
checkNext();
return current != null && current.hasNext();
}
#Override
public T next() {
checkNext();
if (current == null || !current.hasNext()) throw new NoSuchElementException();
return current.next();
}
#Override
public void remove() {
if (current == null) throw new IllegalStateException();
current.remove();
}
private void checkNext() {
while ((current == null || !current.hasNext()) && !iterables.isEmpty()) {
current = iterables.remove(0).iterator();
}
}
}
The concat method to create an Iterable:
#SafeVarargs
public static <T> Iterable<T> concat(final Iterable<T>... iterables) {
return () -> new ConcatIterator<>(iterables);
}
Simple JUnit test:
#Test
public void testConcat() throws Exception {
final Iterable<Integer> it1 = asList(1, 2, 3);
final Iterable<Integer> it2 = asList(4, 5);
int j = 1;
for (final int i : concat(it1, it2)) {
assertEquals(j, i);
j++;
}
}
I would refactor the original design from:
Iterator<User> pUsers = userService.getPrimaryUsersInGroup(group.getId());
Iterator<User> sUsers = userService.getSecondaryUsersInGroup(group.getId());
To something like:
Iterator<User> users = userService.getUsersInGroup(group.getId(), User.PRIMARY, User.SECONDARY, ...);
You can try ConcatIterator from Cactoos:
Iterator<String> names = new ConcatIterator<>(
Arrays.asList("Sarah", "Mary").iterator(),
Arrays.asList("Jeff", "Johnny").iterator(),
);
Also check ConcatIterable, which concatenates Iterables.
In the Apache Commons Collections there is public static <E> Iterator<E> org.apache.commons.collections4.IteratorUtils.chainedIterator(Collection<Iterator<? extends E>> iterators) that says
Gets an iterator that iterates through a collections of Iterators one after another.
which should be what you want.
import java.util.Arrays;
import java.util.Iterator;
import org.apache.commons.collections4.IteratorUtils;
//also works: import org.apache.commons.collections.IteratorUtils;
class Scratch {
public static void main( String[] args ) {
final Iterator<String> combinedIterator = IteratorUtils.chainedIterator(
Arrays.asList( "a", "b", "c" ).iterator(),
Arrays.asList( "1", "2", "3" ).iterator()
);
while( combinedIterator.hasNext() ){
System.out.println( combinedIterator.next() );
}
// "abc123" will have been printed out
}
}
every Iterator object holds own memory location (adress), so you can't simply "merge" them. except if you extend iterator class and write your own implementation there.
If you are dealing with the same number of objects in both iterators an alternative solution would be to process two iterators in one loop like this :
while (iterator1.hasNext() && iterator2.hasNext()) {
// code
}