How does one iterate through a list datastructure using indices. For example consider a sentence in form a list with each element being a word. Can I step through each word using the index? Something like this --
// sentence defined something like this - List<String>
int size = sentence.size();
for (int i=0; i<size-1; i++)
{
System.out.println(sentence[i] + " " + sentence[i+1]);
}
ofcourse the above code doesn't work but is it possible to do something on those lines? As you can see, I want to access the two consecutive elements and using iterators, it starts becoming really messy.
You can use the get(i) method instead of [i]:
for (int i=0; i<size-1; i++) {
System.out.println(sentence.get(i) + " " + sentence.get(i+1));
}
List instances are not the same as arrays. They have specific methods for obtaining items at certain indexes. Try this:
// sentence defined something like this - List<String>
int size = sentence.size();
for (int i=0; i<size-1; i++)
{
System.out.println(sentence.get(i) + " " + sentence.get(i + 1));
}
Now if you had an array (e.g. String[] sentence = new String[]{"hello", "there"}), what you had would work fine.
As a side note, Java has a for-each loop that can be used on both arrays and Lists:
for (String s : sentence) {
// do something
}
Of course, this can't be used in your case because you're accessing elements at multiple indexes in each iteration of your loop - but it's important to know that something like this exists.
The x[i] expression syntax in Java can only be used for arrays. Nothing else.
As other answers have stated, the way to step through the elements of a Java list using indices is to use List.get(int). However, there is an important performance issue that needs to be considered when you do this.
The issue is that the cost of a get(int) call depends on what List implementation class you use:
For an ArrayList (or a Vector) the get(int) operation on a list of length N is O(1). That means that it does not depend on the list length, and in fact it is cheap: only a bit more expensive than an someArray[i].
For a LinkedList, the get(int) operation on a list has to step through the list from the beginning until it reaches the position you asked for. If the list length is N, then the average cost of get(int) (assuming a random position in the list) is O(N); i.e. it is proportional to the list length. If the length is long, then that will be expensive.
By contrast, if you use an Iterator (explicitly, or implicitly by using the for (E e : l) syntax), getting each element will be O(1) for all of the list implementations in java.util and java.util.concurrent (ignoring multi-threading issues such as heavy contention).
Having said that, there are some cases where iterators don't work, and the application needs to use indices.
You can also use Iterator in this case for ex:
first of all put ur elements on arraylist and try to use Iterator like this:
ArrayList arrayList = new ArrayList();
Iterator itr = arrayList.iterator();
while(itr.hasNext())
{
System.out.println(itr.next()); // Print out the elements from arraylist
}
You can process consecutive pairs of values from a list without using indices. Here's one way:
private void processWordsInSentence(List<String> sentence) {
Iterator<String> it = sentence.iterator();
if (it.hasNext()) {
String previous = it.next();
while(it.hasNext()) {
String current = it.next();
// use previous and current values, e.g.
System.out.println(previous + " " + current);
previous = current;
}
}
}
Why would you want to use something like this instead of sentence.get(index)? I would offer a couple of reasons:
In your sample, your processing is really concerned with consecutive
values from the list, not their positions. So there's no "value add"
to having to fiddle with the index explicitly.
Remember that List<T> is an interface with multiple
implementations. ArrayList<T> performs .get(index) in constant
time, but that same call on a LinkedList<T> requires time
proportional to the value of index. So there could be a real performance
consideration.
The processWordsInSentence implementation above does have to deal explicitly with the case of lists with less than two elements. The loop inside the guarding if can be written with a for statement, to separate traversal from processing the actual data a bit more aggressively, if you prefer that style.
private void processWordsInSentence(List<String> sentence) {
Iterator<String> it = sentence.iterator();
if (it.hasNext()) {
for (
String previous = it.next(), current = null;
it.hasNext();
previous = current
) {
// use previous and current values, e.g.
System.out.println(previous + " " + current);
}
}
}
Try this simple code :
List mobileSoftwares = new ArrayList();
mobileSoftwares.add("Android");
mobileSoftwares.add("IOS");
mobileSoftwares.add("Blackberry");
int size = mobileSoftwares.size();
for (int i = 0; i < size - 1; i++)
{
System.out.println(mobileSoftwares.get(i));
}
Related
public ArrayList<String> getWords()
{
int size1 = lines.size();
int size2 = 0;
int counter3 = 0;
ArrayList<Integer> checkthewords;
for (int x = 0; x < size1; x++)
{
size2 = lines.get(x).substring(x).length();
for (int y = 0; y < size2; y++)
{
if (Character.isLetter(charAt(((lines.get(x)).indexOf(x, z + x)))))
{
words.set(z, lines.get(x).substring(x,z + 1));
}
else
{
checkthewords.set(counter3, words);
counter3++;
}
if (checkthewords.get(x).equals(checkthewords.get(counter3)))
{
}
}
}
return words;
}
The method above is a called getWords(). I am trying to get a word from a file and store it in the arrayList checkthewords. I want to make sure that a word is not going to be stored in the arrayList checkthewords more than once.
I have the if statement:
if (Character.isLetter(charAt(((lines.get(x)).indexOf(x, z + x)))))
But, don't know where to go from there.
I'm pretty sure your code won't run at the moment. You are doing some strange things in there and I don't really understand it.
Try to approach this one step at a time.
The first step is to get the word from the file. Make sure you can parse the line and extract the word you want.
Then you need to check if the word exists in your checkthewords list. If it doesn't exist, add it. You can use the contains method provided by List to see if the list contains something.
if(!checkthewords.contains(word)) {
// it's not in the list yet, add it
checkthewords.add(word);
}
Also when you create your checkthewords list, you don't initialise it (so it's null):
ArrayList<String> checkthewords;
should be:
ArrayList<String> checkthewords = new ArrayList<String>();
And you shouldn't use checkthewords.set() like that. set is used to replace an existing element, not to add a new element. You could easily be setting an element that doesn't exist yet and throw an ArrayIndexOutOfBoundsException. Use checkthewords.add(word) to add something to your list.
See the ArrayList documentation.
set(int index, E element)
Replaces the element at the specified position in this list with the specified element.
It seems like you're overthinking this. Keep it simple. :)
You should use Set in Java to store elements when duplicates are not allowed.
A collection that contains no duplicate elements.
If you want to retain insertion order as well then use LinkedHashSet which is Hash table and linked list implementation of the Set interface, with predictable iteration order.
Kindly refer to below tutorials to understand application of Set in java.
Tutorial 1
Tutorial 2
Tutorial 3
See Also-:
HashSet vs TreeSet vs LinkedHashSet
HashSet vs LinkedHashSet
Consider a linked list of strings I got from somewhere
LinkedList<String> names = getNames();
Now, I want to remove the first k elements from the list. Currently, I'll do it this way:
for (int i = 0 ; i < k ; i++) {
names.removeFirst();
}
Is there some way to do it more efficiently and to instead call something like:
names.removeRange(0, k);
Note that I prefer not to construct a whole new list using sublist(), as for small k values, popping k times would be even more efficient than constructing the new list
Maybe Something like this :
names.subList(0, k).clear();
this is more efficient but doesn't release memory according to sublist it's just a view:
names.sublist(k, names.size());
I understand that ArrayList<>'s are fastest for searching (O(1) vs. O(n)) and LinkedList<>'s are fastest for inserting & deleting (O(1) vs. O(n)).
My question is, if using a combination of these two, what is the optimal method to check many lists (>2) for common elements?
Current Method
Using three lists and an iterative method:
out:
for(int a = 0; a < list1.size(); a++) {
for(int b = 0; b < list2.size(); b++) {
for(int c = 0; c < list3.size(); c++) {
if(list1.get(a) == list2.get(b) && list1.get(a) == list3.get(c) ) {
System.out.println(list1.get(a)); // list2.get(b) or list3.get(c) could have been subbed
break out;
}
}
}
}
How can this be optimised for efficiency?
EDIT
Thanks for the many helpful responses :)
What I found to work the best was to use the List .retainAll() function.
Again, to find the common elements among three lists, I have refined the method below.
list1.retainAll(list2);
list1.retainAll(list3);
for(int i : list1) {
System.out.println(i);
}
You can get a expected time linear in the number of elements in all lists, assuming the elements implement hashCode:
public static <T> Set<T> commonElements(List<? extends T> list1, List<? extends T>... lists) {
// use LinkedList for efficient delete operation
// make sure elements are distinct to not check the same element multiple times
List<T> commonElements = new LinkedList<>(new HashSet<>(list1));
for (List<? extends T> l : lists) {
// use HashSet for fast contains check
// keep only elements in the list
commonElements.retainAll(new HashSet<>(l));
}
return new HashSet<>(commonElements);
}
This is faster than your approach, since HashSet allows lookup in O(1) expected time.
Note though that for small input lists the preformance can be much worse with this approach.
If you are looking for performance, it would be better to write an API that uses hash look up. list.retainAll(), though is a single clean api call, internally it does lot of processing especially if the argument passed is also a list. Take a look at the implementation of retainAll() of array list here -
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.retainAll%28java.util.Collection%29
You can look at the implementation of the list that you are using and see if that is okay with your performance requirement. If not, you may try something like this...Write an api to return common elements.
private static Set getCommonElements (List dataList, Set dataSet) {
Set commonDataSet = new LinkedHashSet();
if (dataSet == null || dataSet.isEmpty())
return commonDataSet;
for (Object elem: dataList) {
if (dataSet.contains(elem)) {//Hash based look up. Will be faster.
commonDataSet.add(elem);
}
}
return commonDataSet;
}
Then call that repeatedly as below
Set resultSet= new LinkedHashSet(list1);
resultSet= getCommonElements(list2, resultSet);
resultSet= getCommonElements(list3, resultSet);
If you are not concerned about the order, you can just use a hashset instead of linkedhashset.
One problem with this is, this is iterating over the elements in list which will be higher than the common elements. It would be much better if we can iterate over the common elements and look up in the list. But for that, u may have to keep the data in the lists in a hash-baked list/set or maintain a sorted list. Else the lookup will be costly.
You can optimise it using HashMap in java.
Suppose you have n lists with m elements each
Algorithm :
make hashmap h;
loop i=0 to m
loop j=0 to n
increment j[i] key in hashmap h
loop end
loop end
loop i=0 to m for any list
check hashmap value for the element, if equals to n
print element
complexity o(nm),if n <<< m then, complexity(n)
Using the retainAll(List<>) function instead of iterating over each element has significantly reduced run time and improved readability.
New
list1.retainAll(list2);
list1.retainAll(list3);
Old
out:
for(int a = 0; a < list1.size(); a++) {
for(int b = 0; b < list2.size(); b++) {
for(int c = 0; c < list3.size(); c++) {
if(list1.get(a) == list2.get(b) && list1.get(a) == list3.get(c) ) {
System.out.println(list1.get(a));
break out;
}
}
}
}
Can someone show me how to remove an object from an array. But here's the catch (well for me), the array is something like this
member[0] = new Member("John Cena" , "p000001");
I want to be able to search a name, then when that is detected, to be able to remove. is it possible?
public static void remove(){
System.out.println("Name: ");
String removeName = input.next();
System.out.println("ID: ");
String removeID = input.next();
for(int i = 0; i < member.length; i++){
//not sure if this is the right direction
}
}
EDIT: Cannot use ArrayList or list because of requirements in an Assignment. Would have used it since it is easier but can't.
You can either use an ArrayList (or better yet, ArrayList<Member>), which you can populate with members, and then use the indexOf method to search through.
Alternatively, if you have to or would rather use arrays, create a loop like you have that iterates through each index of your members array. The only tricky part is removal requires that you remove it from the array, and then shift each index in front of it down so that the blank space is remove.
In other words, you need to delete index i and use a loop so that you move the member at i + 1 down to i, member i + 2 moves down to i + 1, and so on until you reach the end of the array.
With all that being said, I'd encourage use of the ArrayList. It does all of the operations I just described for you and makes matters a lot easier.
Arrays are fixed-size. This means that the best you can do for an object array is set the value to null. If you want to remove it completely, you'll want to use ArrayList instead. In that case,
ArrayList<Member> members = new ArrayList<Member>();
for (int i = members.length-1; i>=0; i--) {
if (members.get(i).getName().equals(toRemove)) {
members.remove(i);
}
}
Sorry for my previous wrong answer. This should be the correct way of removing your Members
List<Member> l = new ArrayList<>(Arrays.asList(member));
for (Iterator<Member> iter = l.listIterator(); iter.hasNext(); ) {
Member a = iter.next();
if ( (a.getId() == removeID) || (removeName.equals(a.getName)) ) {
iter.remove();
}
}
Member[] newMembers = l.toArray(new Member[l.size()]);
PS: Please get removeID like this;
int removeID = input.nextInt();
It's a bit wonky that you have to use an array, because:
You can't truly guarantee that there isn't going to be more than one person with the same name, since the array doesn't guarantee unique entries.
Arrays don't dynamically resize, leaving you to have to do that yourself.
It can still be done though. Here's an example using Java 8's Stream API.
Let's assume you're looking for a Member with the same name and ID. Then, you're going to want to filter out any elements that are not that entry, collect them to a List, and then turn that List into an array.
So the result would be:
member = Arrays.stream(member)
.filter(m -> removeName.equals(m.getName())
&& removeID.equals(m.getID()))
.collect(Collectors.toList())
.toArray(new Member[0]);
I'm just starting to work with lists in java. I'm wondering what the recommended method to modify each element of a list would be?
I've been able to get it done with both the following methods, but they both seem fairly unelegant. Is there any better way to get this done in java? And is any of the below methods recommended over the other, or are both on the same level?
//Modifying with foreach
for (String each : list)
{
list.set(list.indexOf(each), each+ " blah");
}
//Modifying with for
for (ListIterator<String> i = list.listIterator(); i.hasNext(); i.next())
{
i.next();
list.set(i.nextIndex()-1, i.previous() + " blah yadda");
}
The second version would be better. Internally they are the same in the end, but the second actually allows you to modify the list, while the first one will throw a ConcurrentModificationException.
But then you are using the Iterator in a wrong way. Here is how you do it correctly:
for (final ListIterator<String> i = list.listIterator(); i.hasNext();) {
final String element = i.next();
i.set(element + "yaddayadda");
}
The iterator is the one that needs to modify the list as it is the only one that knows how to do that properly without getting confused about the list elements and order.
Edit: Because I see this in all comments and the other answers:
Why you should not use list.get, list.set and list.size in a loop
There are many collections in the Java collections framework, each on optimized for specific needs. Many people use the ArrayList, which internally uses an array. This is fine as long as the amount of elements does not change much over time and has the special benefit that get, set and size are constant time operations on this specific type of list.
There are however other list types, where this is not true. For example if you have a list that constantly grows and/or shrinks, it is much better to use a LinkedList, because in contrast to the ArrayList add(element) is a constant time operation, but add(index, element), get(index) and remove(index) are not!
To get the position of the specific index, the list needs to be traversed from the first/last till the specific element is found. So if you do that in a loop, this is equal to the following pseudo-code:
for (int index = 0; index < list.size(); ++index) {
Element e = get( (for(int i = 0; i < size; ++i) { if (i == index) return element; else element = nextElement(); }) );
}
The Iterator is an abstract way to traverse a list and therefore it can ensure that the traversal is done in an optimal way for each list. Test show that there is little time difference between using an iterator and get(i) for an ArrayList, but a huge time difference (in favor for the iterator) on a LinkedList.
EDIT: If you know that size(), get(index) and set(index, value) are all constant time operations for the operations you're using (e.g. for ArrayList), I would personally just skip the iterators in this case:
for (int i = 0; i < list.size(); i++) {
list.set(i, list.get(i) + " blah");
}
Your first approach is inefficient and potentially incorrect (as indexOf may return the wrong value - it will return the first match). Your second approach is very confusing - the fact that you call next() twice and previous once makes it hard to understand in my view.
Any approach using List.set(index, value) will be inefficient for a list which doesn't have constant time indexed write access, of course. As TwoThe noted, using ListIterator.set(value) is much better. TwoThe's approach of using a ListIterator is a better general purpose approach.
That said, another alternative in many cases would be to change your design to project one list to another instead - either as a view or materially. When you're not changing the list, you don't need to worry about it.
Internally there in Iterator for for-each implementation. So there is no deference between these two cases. But if you trying to modify element it will throws ConcurrentModificationException.
I got mine working this way
String desiredInvoice="abc-123";
long desiredAmount=1500;
for (ListIterator<MyPurchase> it = input.getMyPurchaseList().listIterator(); it.hasNext();) {
MyPurchase item = it.next();
if (item.getInvoiceNo().equalsIgnoreCase(desiredInvoice)) {
item.setPaymentAmount(desiredAmount);
it.set(item);
break;
}
}