I wrote a custom iterator class that iterates over the set of numbers found in a PoSet, and here is my code:
private class IntGenerator implements Iterator {
private Iterator<Integer> i;
private Set<Integer> returnedNumbers;
public IntGenerator () {
returnedNumbers = new HashSet<Integer> ();
i = S.iterator();
}
public boolean hasNext() {
return i.hasNext();
}
public Object next() {
int n = i.next();
for (Pair p : R) {
if (isInSecondElmPair(p, n)) {
if (returnedNumbers.contains(p.getFirstElm())) {
returnedNumbers.add(n);
return n;
}else{
returnedNumbers.add(p.getFirstElm());
return p.getFirstElm();
}
}else if (isInFirstElmPair(p, n)){
returnedNumbers.add(n);
return n;
}
}
return n;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
The thing is that when returning a number, I should abide by the partial order rules, that is:
1. if (x, y) belongs to R, then x should be returned before y
However the code above seems to follow that ordering but it is creating duplicates, how can I fix my code to not allow it?
NOTE: In my code, S is the set of numbers in the PoSet, it is a HashSet and R is an arraylist of pairs (pair: a class i created that takes 2 ints as param) to hold the relations in the PoSet.
Is there any way to fix this problem?
Thanks
Your next method always calls i.next(), and returns one of two things:
the value that i.next() returned
some value that is less than that value.
This means that if your poset contains {1,2,3,4} and uses the natural ordering for integers, and i.next() returns 4, then either you return 4 now (due to 1, 2, and 3 already having been returned), or you will never return 4 (because it's not less than any future value).
The reason you're getting duplicates is that you return one value for every value of i.next(), and there are some values that never get returned (see previous paragraph), so naturally there are some values that get returned multiple times in compensation. Note that you never check whether the value returned from i.next() has previously been returned by your next() method, so if an element in the poset is not greater than any other element, then when i.next() returns that element, your next() method will automatically return it, even if it has previously returned it.
I think the only sensible fix for this to completely change your approach; I don't think your current approach can readily be made to work. I think your iterator's constructor needs to copy all the elements of the poset into an acceptably-ordered list, and then the next() method will simply return the next element of that list. Or, alternatively, since your current approach already requires iterating over R on every call to next() anyway, it might make more sense to base your iterator on an iterator over R. (I'm assuming here that R is already ordered using itself; if it's not, then your for loop makes no sense at all, and will essentially return randomly selected elements.)
If you do want to try to stick with your approach, then you'll need to keep track not only of the elements that your next() method has returned, but also of the elements that i.next() returned but that your next() method did not return; you'll need to be able to return these elements later.
Also, your for (Pair p : R) loop doesn't do what you want — it automatically returns n as soon as it finds any element that is less than n that's already been returned, even if there are other elements less than n that haven't been returned yet. (This is if R is already ordered using itself. If it isn't, then this loop has even bigger problems.)
Related
I'm using
Collections.synchronizedList(new ArrayList<T>())
part of the code is:
list = Collections.synchronizedList(new ArrayList<T>());
public void add(T arg) {
int i;
synchronized (list) {
for (i = 0; i < list.size(); i++) {
T arg2 = list.get(i);
if (arg2.compareTo(arg) < 0) {
list.add(i, arg);
break;
}
}
Is it right that for loop is actually using iterator and therefore I must wrap the for with synchronized?
Is it thread-safe to use synchronized and make addition inside it like I did here?
I'm sorry if these questions are very basic, I'm new to the subject and didn't find answers on the internet.
Thank you!!
Is it right that for loop is actually using iterator and therefore I must wrap the for with synchronized?
There are two parts to your question.
Firstly, no, you're not using an iterator here, this is a basic for loop.
The enhanced for loop is the for loop which uses an iterator:
for (T element : list) { ... }
You can see in the language spec how this uses the iterator - search for where it says "The enhanced for statement is equivalent to a basic for statement of the form".
Secondly, even though you're not using an iterator, you do need synchronized. The two are orthogonal.
You are doing multiple operations (the size, the get and the add), with dependencies between them. You need to make sure that no other thread interferes with your logic:
the get depends on the size, since you don't want to try to get an element with index >= size, for instance;
the add depends on the get, since you're apparently trying to ensure the list elements are ordered. If another thread could sneak in and change the element after you get it, you might insert the new element in the wrong place.
You correctly avoid this potential interference this through synchronization over list, and creating the synchronizedList in such a way that nothing other than the synchronizedList can get direct access to the underlying list.
If your arg2.compareTo(arg) never return 0 (zero) you can use TreeSet. Will be much more simple:
set = Collections.synchronizedSet(new TreeSet<T>());
public void add(T arg) {
set.add(arg);
}
If you need hold same items (compareTo returns 0) then use the list:
list = new ArrayList<T>();
public void add(T arg) {
synchronized (list) {
int index = Collections.binarySearch(list, arg);
list.add(index, arg);
}
}
First and second cases complexity will be log(N) (10 for 1000 items). Your code complexity is N (1000 for 1000 items).
My texted book that uses an inner class as an iterator says that the method hasNext is just return current < this.size; where current is the current index. But if the size is 3 and the index is 2, there wouldn't be a next value, so why wouldn't it be < size - 1
I am not sure which Iterator implementation your are referring to but talking about java implementation it is like below:
public boolean hasNext() {
return cursor != size; //cursor is the index of next element to be fetched
}
So the implementation you are referring to I believe current actually refers to the element to be fetched next.
Lets take your example:
Size : 3
current : 2
condition: 2<3(true) returns true and next() gets you the list.get(current)
Size:3
current :3
Condition : 3<3(fail) you don't have anymore element to iterate as you reached to the end.
Depends on what you are doing in next method. Check the code from ArrayList.Itr implementation. Here is one way of implementing scenario you described(this is similar to ArrayList.Itr implementation),
current initially points to 0.
When next is called, current value of current is saved to a variable, say, i. current is incremented.
The value at index i is returned.
In above case if the current value is 3, there are no more elements. The logic is right. The iterator have elements as long as current<size.
Probably because it hasn't given the value at the index current yet. The function hasNext just tells you if there is something left to get out of an Iterator. For example if you'd like to print all the contents of an Iterator you would do something like this:
while (iterator.hasNext()) {
System.out.print(iterator.next());
}
Where the functions hasNext and next would be defined as something like:
public boolean hasNext() {
return current < this.size;
}
public T next() {
return this.array[current];
current++;
}
The idea of LinkedList is, that each element has a reference to its successor (and predecessor in the case of doubled linked list), so concatenation of two LinkedLists happens that last element of the first list get reference to first element of second list Detailed explanation here, what is made in O(1) time.
Howewer they made it stupid in Java.
It has no method java.util.LinkedList.addFirst(LinkedList) or something.
if you look at the method java.util.LinkedList.addAll(Collection), it iterates over an array, what collection returns with c.toArray(), and then adds each element of this array. What is even twice stupid:
1) linked list is iterated in 0(n)
2) elements are added to linked list in 0(n) time.
Is there any possibility to extends the standart LinkedList so he would have good concatenation method? Because now, the simplest, but bad solution i see to make the copy- paste of LinkedList code and make some methods protected in order to extend that with implementation of right addALL
You can't use addAll for that, because O(1) linked list concatenation is a destructive operation. In other words, you start with two non-empty lists, and end up with one big list and one empty list.
You are looking for two operations
void transferBeforeFirst(LinkedList<T> other);
void transferAfterLast(LinkedList<T> other);
They take LinkedList<T> other in whatever state it may be, and leave it empty upon return. This is rather counterintuitive, because generally the caller expects to find his data unchanged after calling a library method.
Of course, technically this could certainly be done. However, this goes against the grain of Java API design, which prefers to leave method parameters unchanged.
I don't think there is a way to do that, and the reason is that java has a strong object orientation and doesn't operate with data in a direct way such has C does, so if you have two linked lists and you want to make one out of two, you are forced to copy one of them entirely instead of only liking it at the end of the other one.
This behaviour is because special casing the adding of two linked lists together would destroy the sconfd list.
Notice that the LinkedList.Node class has both a next and a prev so it is indeed doubly-linked. To just join the chains together would make list2.first.prev point to list1.last which would then break list2.
public void addLast(LinkedList<? extends E> l) {
// My list continues on into the new list.
last.next = l.first;
// Back-link too - THIS BREAKS l!!
l.first.prev = last;
// End of new list is now last.
last = l.last;
}
Secondly notice that LinkedList<? extends E>. Remember that you can extend LinkedList so you may be adding two lists of a completely different class together - that would also require careful handling.
If you really want to achieve O(1) you could write an IterableIterable that would walk an Itearble<Iterable<T>> delivering each element from each Iterable in turn - kind of like a flatMap for Iterables.
class IterableIterable<T> implements Iterable<T> {
private final Iterable<? extends Iterable<T>> i;
public IterableIterable(Iterable<? extends Iterable<T>> i) {
this.i = i;
}
#Override
public Iterator<T> iterator() {
return new IIT();
}
private class IIT implements Iterator<T> {
// Pull an iterator.
final Iterator<? extends Iterable<T>> iit = i.iterator();
// The current Iterator<T>
Iterator<T> it = null;
// The current T.
T next = null;
#Override
public boolean hasNext() {
boolean finished = false;
while (next == null && !finished) {
if (it == null || !it.hasNext()) {
if (iit.hasNext()) {
it = iit.next().iterator();
} else {
// All over when we've exhausted the list of lists.
finished = true;
}
}
if (it != null && it.hasNext()) {
// Get another from the current list.
next = it.next();
}
}
return next != null;
}
#Override
public T next() {
T n = next;
next = null;
return n;
}
}
}
That's why LinkedList has the addLast() method
https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#addLast%28E%29
and it does have a addFirst() too
https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#addFirst%28E%29
you can't do better than that, because Java has not the pointer concept.
you could try to implement your own native code for that, however.
I'd like to store a list of numbers 1,2,3,4 - (lets start with List<Integer>)
I'd like to make sure numbers are unique (ok, fine, Set<Integer>)
I'd like to guarantee order (ok ... LinkedHashSet<Integer>)
I'd like to get the last element from the list ..
What would be the simplest way to get the last number inserted into the LinkedHashSet<Integer> please?
There's no prebaked option for this. There's two off-the-cuff options, and neither are good:
The Order n approach:
public <E> E getLast(Collection<E> c) {
E last = null;
for(E e : c) last = e;
return last;
}
Yuck! But there's also an Order 1 approach:
class CachedLinkedHashSet<E> extends LinkedHashSet<E> {
private E last = null;
#Override
public boolean add(E e) {
last = e;
return super.add(e);
}
public E getLast() {
return last;
}
}
This is off the cuff, so there might be a subtle bug in it, and for sure this isn't thread safe or anything. Your needs may vary and lead you to one approach over another.
With java-8, you could get a sequential Stream of the LinkedHashSet, skip the first n-1 elements and get the last one.
Integer lastInteger = set.stream().skip(s.size()-1).findFirst().get();
First of all, I agree with corsiKa's solution which suggests an extended version of LinkedHashSet class that contains a pointer to the last element. However, you can use a traditional way by consuming some space for an array:
set.toArray()[ set.size()-1 ] // returns the last element.
here is a implementation that adds method to access the last entry O(1):
LinkedHashSetEx.java
enjoy...
Sets are independent of order.We cannot access element by index.If you require last element,
1)create new ArrayList(Set)
The last element of an arrayList can be accessed easily
Recursion is a new practice for me and I am trying to get better at it and understand how the methods return. I have the following program but am unfailiar with how to use the this keyword. Can you please review the code and walk me through the program showing the values held by the variables as the methods execute?
I have tried numerous things to determine how the value answer in the compute method holds 14 after execution can anyone walk me through the first few recursive calls so I can try and figure out the rest?
public class Recurs1 {
public static void main (String [] arg) {
Recurs1 r = new Recurs1();
r.compute();
}
public void compute() {
int [] stuff = {1, 2, 3, 4};
int answer = this.go(stuff, 0);
System.out.println("The answer is " + answer);
}
private int go(int[] numbers, int spot) {
if (numbers.length == spot) return spot;
int value = this.go(numbers, spot + 1 );
return value + numbers[spot];
}
}
Ok so a few things I notice here:
The purpose of go() seems to be calculating the sum of the numbers in the array. If this is the case, your method should look like this:
private int go(int[] numbers, int spot) {
if (numbers.length - 1 == spot) return numbers[spot];
int value = this.go(numbers, spot + 1 );
return value + numbers[spot];
}
This is because numbers.length in this case will return 4, but the last element in this array is at index 3 (arrays are 0-indexed).
This way, when the function is called with the second parameter set to 3, it will return the value of the last element in the array and then the code will "bubble up" (as I like to call it) and calculate the sum of the elements by subsequently returning the current summed value + the value of the current call.
As for your problem with the this keyword, it's actually very simple. this always refers to the current class instance your code is in. In this case, you create a Recurs1 instance called r in your main function so whenever you call a method on that particular object, the this keyword used in those methods will refer to r. If you created multiple Recurs1 objects (each with potential different internal states) in your program, their respective this references would always point to themselves allowing you to access their member variables and methods.
Hope that helps and good luck, recursion is usually what most people have trouble getting their heads around at first but once you get used to it it's pretty cool!
OK so this is not an answer to your question per se, more like a lesson in recursion.
Keep in mind I have never tried to to do this with a java class.
Recursion means a function that calls itself repeatedly until a answer has been reached, or your function detects you are running out of stack space.
You first step into the function determines if you will call yourself.
When you call yourself you will push a new copy of the data onto the stack and begin executing. I think in the case of java you will allocate a new object into the heap ( don't quote me on this ) and each invocation will have a new set of variables that get populated with new values.
As you recurse deeper and deeper you simply allocate new copies of the object until you find the answer or run out of memory.
If you find the answer you then return the result to the previous level in the stack of objects eg:
int foo(int i ){
if(some condition){
return foo(i);
} else
return i
}
as You can see if the condition tests true the foo() keeps getting called. Now at each call, the variables of foo() are saved for as many levels deep as you go. If the condition tests false then each instance of foo() returns to the previous until you are at the original invocation of foo() which then returns to the caller of foo().
Clear as Mud?