Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Just took a quiz in a CS course I'm in, and I wanted to compare my thoughts with what you guys know. The question asked "Which of the following data structures can be stepped through with an Iterator?" and the options were "ArrayList, an array-based implementation of the QueueADT, and an array-based implementation of the StackADT." You could select more than one, but I only selected ArrayList -- I thought that iterators could only step through Object data structures, and since the ADTs were implemented using arrays, an Iterator couldn't be used on them. Is my thinking incorrect here?
The question is a bit, eh... unclear.
The for-each sense
If the sense is 'what can you use the for-each construct on', then the answer is: instances of Iterable, and arrays:
int[] a = new int[10];
for (int b : a) { .... }
is legal, even though a is not iterable. An Iterable is defined as: has the method public Iterator iterator() { .. }. So Iterators aren't iterable, but something like ArrayList implements Iterable.
In that sense, arrays are a lot like iterables: You can step through them. Just, not with an iterator, unless...
The 'an iterator could be made' sense
Hey, I can make ya an iterator that iterates over an array, no problem:
String[] arr = new String[10];
return new Iterator<String>() {
private int idx = 0;
public boolean hasNext() { return idx < arr.length; }
public String next() { return arr[idx++]; }
};
So, can you iterate through an array using an iterator? I guess so. Only took 5 lines.
The 'array-based' doesn't mean 'array' interpretation
ArrayList is an array-based implementation of List. Hence the name ArrayList. It is iterable and will return iterators. That implementation looks a lot like what I wrote in the previous section.
Assuming QueueAdt is a reference to this - then QueueADT is analogous to List (an interface that just defines operations), and "an array-based implementation of QueueADT" would then be analogous to ArrayList. However, one crucial difference is that the List interface itself demands that any implementation is Iterable<T>, whereas the QueueADT interface doesn't require this, assuming I linked to the right code. Nevertheless, implementations (subtypes) can add extra features if they want. This is perfectly legit:
public class ArrayQueueAdt<T> implements QueueADT<T>, Iterable<T> {
private final Object[] array;
#Override public Iterator<T> iterator() {
// something like the above
}
public void enqueue(T element) {
// impl here
}
// etcetera
}
In the 'arrays are Iterators or Iterable' sense
Then no. Arrays do not implement Iterable, and they do not have an iterator() method. The idiomatic java way to turn an array into an iterable or iterator is: Arrays.asList(theArray), which is lightweight (doesn't copy anything) and is Iterable. Arrays.asList(theArray).iterator() similarly, is a lightweight (no copies) way to get it. So, maybe?
They don't HAVE to (because QueueADT doesn't declare it, whereas List does).
So, the answer is pretty much ¯\(ツ)/¯ I guess yes, because the answer in all these senses is yes, or maybe.
Related
This question is similar to What is the best way to filter a Java Collection? "filter a java.util.Collection based on a predicate." with the additional requirements that
The filter be done in place (O(1) memory excluding the input) because the list is large
No external libraries (i.e. Guava, Apache commons, etc.) may be used
Java 7 compatible (no Java 8 streams)
We can make the assumption that the java.util.Collection type is a java.util.List that implements .remove(int)
Possible solutions:
Use the .remove() method on an Iterator of the List. This could throw an UnsupportedOperationException since the .remove() method is optionally supported on Iterator
Write our own iterator that iterates through the list using an index, .size(), and .remove(int)
Are there any simpler solutions?
Is Iterator.remove() implemented for all standard Java Lists and/or Collections that implement .remove(int)?
There is no optimal solution that fits all Lists and that’s where you can never reach the efficiency of Java 8, as, being an interface method, Java 8’s default method can be overridden by any List implementation providing an implementation tailored for that particular class.
When you want to do a reasonable implementation of a similar feature in pre-Java 8, you have to focus on the common cases. There are almost no JRE provided lists for which remove(int) works but Iterator.remove doesn’t1. But consider that the ArrayList is the most used mutable List implementation and for that implementation, an iterator based solution will perform poorly for large list and lots of removed items. This is because every remove operation, regardless of whether you are using remove(int) or Iterator.remove, will shift all subsequent items by one position before you can proceed and possibly will remove again an item. In the worst case, having a predicate matching all items, that would impose a quadratic complexity. So it’s important to provide a more sophisticated solution for that case:
interface Predicate<T> {
boolean test(T object);
}
public static <T> boolean removeIf(List<T> list, Predicate<? super T> p) {
if(list instanceof RandomAccess) {
int num=list.size();
BitSet bs=new BitSet(num);
for(int index=0; index<num; index++) {
if(p.test(list.get(index))) bs.set(index);
}
if(bs.isEmpty()) {
return false;
}
for(int dst=bs.nextSetBit(0), src=dst;; dst++, src++) {
src=bs.nextClearBit(src);
if(src==num) {
list.subList(dst, src).clear();
break;
}
list.set(dst, list.get(src));
}
return true;
}
else {
boolean changed=false;
for(Iterator<T> it=list.iterator(); it.hasNext(); ) {
if(p.test(it.next())) {
it.remove();
changed=true;
}
}
return changed;
}
}
In the case of lists implementing RandomAccess, which includes all arraylist style implementations, the solution will mimic something similar to Java 8’s ArrayList.removeIf implementation though we don’t have direct access to the internal array and I left out all fail-fast concurrent modification detection stuff. Now, for ArrayList kind of lists it will have linear complexity and so it will have for LinkedList, as it doesn’t implement RandomAccess and thus, will get processed using its Iterator.
The method also fulfills the contract of Java 8’s removeIf method of returning whether the list has been changed by the operation.
1 CopyOnWriteArrayList is an exception but for a copy-on-write list the idea of an in-place removeIf is moot, unless provided by the list itself, as, when implementing it via its remove(int) (or any other public) operation we’re effectively copying the entire list on each change. So in that case, copying the entire list into an ordinary list, performing the removeIf on that list and copying it back will be more efficient in most cases.
Filters and Predicates are Java8 types, so if you don't want to use Java8, you need something similar.
You could fake the filter with an wrapped Iterator and make it work with an object (similar to how Prediates could be implemented); however, there are secondary questions:
You state the list is quite large, and the memory impact of the solution should be O(1) but such a thing is impossible to guarantee without knowing the list being operated upon. The remove(int) operator could allocate a new list index and copy into it, within the implementation.
Assuming the list does no such thing, the best you can do is implement your own iterator that takes a Predicate like test, or write a specific loop to handle the list.
In any case, this sounds like an interview question. Here's one example
public interface MyPredicate<T> {
public boolean isTrue(T value);
}
public void removeOnTrue(List<T> list, MyPredicate<T> predicate) {
Iterator<T> iterator = list.iterator();
while (iterator.hasNext()) {
T next = iterator.next();
if (predicate.isTrue(next)) {
iterator.remove();
}
}
}
doing it with a for loop across indexes is about the same, except that you would then have to keep track of the index (and remove using index).
To use the above example:
...
List<String> names = ...;
removeOnTrue(names, new MyPredicate<String>() {
public boolean isTrue(String value) {
return value.startsWith("A");
}
});
...
would yield a names with all strings starting with "A" removed.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Following situation:
I've created some methods, that allow me to manipulate a List. For a simple example these methods are addSomeElements(...) and removeSomeElements(...)
What is the best approch to call those methods? I know following ways to do that, but don't know which one's the best?!
1) re-initialize the list
private void doSomething(List<String> list) {
list = addSomeElements(list);
list = removeSomeElements(list);
}
In this case the methods would of course have to return a list:
private List<String> addSomeElements(List<String> list) {
list.add(...);
return list;
}
2) create new variables
private void doSomething(List<String> list) {
final List<String> list2 = addSomeElements(list);
final List<String> list3 = removeSomeElements(list2);
}
private List<String> addSomeElements(List<String> list) {
final List<String> newList = new ArrayList<String>(list);
newList.add(...);
return newList;
}
3) work with void methods
private void doSomething(List<String> list) {
addSomeElements(list);
removeSomeElements(list);
}
private void addSomeElements(List<String> list) {
list.add(...);
}
This would be the easiest way, but I don't really like it, because I think for the user it's not always obvious what you're doing. If you have an int for example, you would declare it like int myInt = 0. When you want to change the value, you could just say myInt = 1. It's clear that myInt has now a new value. But with the list it's different. The list you want to change might just be one of several parameters of the method you wanna call to modify the list. The user may probably not recognize that you've modified the list, which seemed to be only a Parameter, if the naming of the method doesn't tell it.
What would be the "cleanest" approach here?
If you're modifying the list passed into your method, don't return the list reference (your option #1 and option #2 since edited); it gives the impression at the API level that you're creating a new list, not modifying the one you were given.
That leaves you with two choices, either of which is "best practice" depending on context:
Modify the list passed in, and use void methods (or methods that return something else entirely if appropriate). (This is your option #3.)
Create new lists with the additions/removals, and return a reference to the new list. (This is like your edited option #2, but note that you would also have to return list3 out of doSomething for it to make sense.)
I recommend creating new lists instead of manipulating existing instances. Working with immutable state (which means copying state instead of modifying state) generally leads to cleaner code and less bugs. So I recommend going on the 2) way.
The mutable approach (modifying an existing list) may be faster, but don't go this way unless you have a very good reason to optimize.
Hey guys I've been teaching myself java and I working on this assignment.
http://ljing.org/games/focus/
So I write a Linked list from scratch, I write a Deque class using the LinkedList class
But!
There's only one question I don't understand about the classes Iterator.
I just don't understand what does the Class Deque Iterator is supposed to do.
Also, I have this in my code:
class Deque<Item> implements Iterable<Item>.
But then the compiler complains that in my Deque class I need to override a method
#Override
public Iterator<Item> iterator()
{
throw new UnsupportedOperationException("Not supported yet.");
}
But I don't understand why
There are two different interfaces in Java for iteration that are important, Iterable and Iterator. They each serve a different purpose.
Iterable
When something implements this interface, this means that it can be iterated on. This is useful for us because Java gives us a shortcut for iterating over things that implement Iterable using a for-each loop:
List<String> elements = ... ; // List is an instance of Iterable
for (String element : elements)
System.out.println(element);
Anything that is an instance of Iterable can be used in a for-each loop. If you have your own custom MyDeque class that implements Iterable, then you can use that in a for-each as well:
MyDeque<String> elements = ... ;
for (String element : elements)
System.out.println(element);
This brings us to...
Iterator
This interface is how the iteration is actually performed. The for-each loop compiles to something like this:
MyDeque<String> elements = ... ;
for (Iterator<String> $iter = elements.iterator(); $iter.hasNext();) {
String element = $iter.next();
System.out.println(element);
}
This piece of code is functionally equivalent to the for-each above. hasNext() is the continuation condition (do I have more stuff to give you?) and next() actually gives you the next element, or throws a NoSuchElementException if we don't have anything else.
The point of making your custom deque implement Iterable is just to make it so you can iterate over the elements in your deque using something like a for loop. Its Iterator implementation is the thing that will let you actually do that iteration.
An iterator is a concept for accessing the elements in a collection. Because you say implements Iterable<Item>, you tell the compiler that you provide this mechanism of accessing the elements of your Deque. But that's not enough yet. Besides claiming you will do it, you actually have to do it. In this case, doing it is implementing the method.
What happens if you don't:
Because you told the compiler you would provide this, you have to implement the method iterator(), which is part of this access concept. If you do not implement the method, the compiler complains and tells you "hey, you said you would do it. So keep your word!".
There are two ways to solve this:
1.) In the first place, don't give your word you would provide the access concept through an iterator - remove implements Iterable<Item>
2.) Keep your word and implement the method. You will have to write an own Iterator class for this. That's a rather short task once you know what to do.
This question already has answers here:
Merge two lists in constant time in Java
(4 answers)
Closed 9 years ago.
I have two LinkedList in my code and I need to make one that have both. I will not need this Lists anymore, just the new one, which have all data I need.
I could use .addAll(), but performance is I huge issue and I cant wait to copy,adding references, everything every time..
I am looking for something like we normally do if we create our own linkedlist, just connect the last node from one to the fist from the second.. Is there a way to do that using the LinkedList class from the java api?
Merging collections is a different case, although the operation means almost the same, my issue is just regarding performance and just for linkedlists, which normally can do what I need. Also "merging" is kind of an ambiguous term, what I want is just to put then together no matter what order they are, with performance in mind.I am not looking if is possible to merge...
Another thing, my question is just regarding the API, I am not looking for building my own code (boss requirement) and that is why is different from this one: Merge two lists in constant time in Java - not useful answers there either..
If you are using LinkedList then you are most likely not interested in indexed access (since indexed access is slow... but keep in mind that a list only stores references, so for very large lists with few insert/removes you are going to be more memory efficient with an ArrayList as it doesn't need to allocate each node on the heap)
So what you actually want is something that gives you most of the List contract... or maybe not even that.
It could well be that all you want is something that gives you Iterable<String>... if that is the case then you have a very easy life:
public class UberIterable<T> implements Iterable<T> {
private final List<List<T>> lists;
public UberIterable(List<T>... lists) {
this.lists = Arrays.asList(lists);
}
public Iterator<T> iterator() {
return new Iterator<T>() {
Iterator<List<T>> metaNext = lists.iterator();
Iterator<T> next;
public boolean hasNext() {
while (true) {
if (next != null && next.hasNext()) return true;
if (metaNext.hasNext()) next = metaNext.next(); else return false;
}
}
public T next() {
if (!hasNext()) throw new NoSuchElementException();
return next.next();
}
public void remove() {
throw new UnsupportedOperation();
}
}
}
}
That is a basic implementation that will give you a merged view of many lists. If you want to get more of the contract of List you could repeat the same tricks only with a better implementation of ListIterator which will get a lot of what you are probably after, or finally by extending AbstractList and overriding the appropriate methods with your new ListIterator implementation
If you only want to iterate over the new list and you can replace List with Iterable you can use Guava's Iterable.concat as described here:
Combine multiple Collections into a single logical Collection?
I'm afraid the answer is no. The internal Entry class used by LinkedList is private, and all the public methods exposed by LinkedList work with general collections.
Your use case seems reasonable to me, but this implementation doesn't support it.
I'm afraid that the only way to do this is by using reflections... When you take a look at the source code of LinkedList, you can see that the subclass Entry<E> is private, which is a problem if you want to connect the first and last entries to other entries, in order to merge the list.
Update: Even reflections are not safe (unless you add checks), because Oracle changed the name of the subclass Entry to Node and changed the order of arguments of the constructor! in JDK 7, which is stupid IMHO.
Dirty solution: Do a whole copy paste of the source code and change the private keywords to public. However, I'm not sure this is allowed by Oracle. Check their license.
One way you could go about doing this is by using getLast() to grab the last element off the one of the lists and then use addFirst() on the other in order to add it to the front.
As has been said here, however, addAll() would not be copying anything and could be used just as easily.
If your issue is with the actual instantiation of node objects in the LinkedList, you may need to implement your own version that exposes more of the implementation mechanisms in its API.
why not create a wrapper/proxy class that implements List and contains references to the 2 sublists, then implement the List methods (or at least the ones you need downstream) - a little bit of work but if copying either of the lists is really the issue sounds like it is worth it.
import java.util.LinkedList;
public class MergeLinkedList {
public static void main(String[] args) {
LinkedList<String> mainlist = new LinkedList<String>() ;
mainlist.add("A");
mainlist.add("B");
LinkedList<String> secondlist = new LinkedList<String>() ;
secondlist.add("C");
secondlist.add("D");
mainlist.addAll(secondlist);
System.out.println(mainlist);
}
}
O/P
[A, B, C, D]
you have to use addall();
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
When to use LinkedList<> over ArrayList<>?
I saw the API for the ArrayList and LinkedList and it seems to be same. Apart from their performance difference is there any difference in terms of adding, deleting and iterating the List.
List arrList = new ArrayList();
List linList = new LinkedList();
The List arrList or linList reference is actually implementing the corresponding class. What does this actually mean?
As far as your first question goes: their performance and their memory usage the only differences that will matter to you (the third one, their actual implementation details, aren't your concern.) LinkedLists use more memory, and getting, say, the 22nd element by walking through the list from the head is very slow; but they're terrific as far as adding and removing elements in the middle of the list. ArrayLists use less memory, and getting the 22nd element is very fast -- but inserting or removing an element in the middle takes time proportional to the size of the list.
As far as your second question goes: the statement that the reference is "actually implementing the list" is just wrong, so I don't really know how to answer it. The reference variable refers to an object that implements the List interface; both of these two classes implement that interface, so a reference of type List can refer to objects of either class.
I am not 100% sure what you mean when you ask "What does this actually mean?", but here is a guess.
Consider code like this:
interface Interface
{
void foo();
}
class Implementation
implements Interface
{
public void foo() { }
public void bar() { }
}
public class Main
{
public static void main(final String[] argv)
{
Interface a;
Implementation b;
a = new Implementation();
b = a;
a.foo();
b.foo();
a.bar(); <- won't compile
b.bar();
}
}
Interface a; and Implementation b; both point at the same object, but only the reference to "b" has access to the "bar" method.
So, in your example, any methods that are in the List interface are accessible to both arrList and linList, but any methods that they provide in addition to the List interface wont be callable without a cast. You can (and should in most cases) treat ArrayList and LinkedList as a List.
For the specifics of inserting/adding/deleting from the different lists, you generally should not care. Both behave the same way from the point of view of the end result (eg. the same sequence of method calls with the same data will result in the same result, just the internal layout will be different).
There's a good discussion of the pros and cons of these two List implementations in the Java tutorial. See the topic on List Implementations.
ArrayList is backed by an array which is resized when needed. LinkedList is made of of element nodes with references pointing to the previous and next node. There are numerous posts on this site discussing the differences, just search for them.