简体   繁体   中英

how to look 'n' elements ahead while iterating through java list?

I've a linked list with some elements.

 { (?i), \\d+, \\., \\d+, (?i), \\d+, \\. }

Now, while iterating, I need to find out if three consecutive values are "\\\\d+", "\\\\.", "\\\\d+" , if yes, I need to merge them into one node with value "\\\\d+\\\\.\\\\d+" . So, my previous list should look like the below after the said operation.

{(?i), \\d+\\.\\d+, (?i), \\d+, \\.}

But, as java doesn't expose linked list's internal node class there is no way for me to look ahead more than one node at a time. I could get it working with the following code, but it looks ugly to me. I'm wondering if there is any clean way of achieving the same.

LinkedList<String> l = new LinkedList<>(); //this can be ArrayList aswell. 
l.add("(?i)");
l.add("\\d+");
l.add("\\.");
l.add("\\d+");
l.add("(?i)");
l.add("\\d+");
l.add("\\.");
System.out.println(l.toString());
List<Integer> indexesToBeRemoved = new ArrayList<>();
for (int i = 0; i < l.size(); i++) {
    int j = i;
    if ("\\d+".equals(l.get(j))) {
        j++;
        if (j < l.size() && "\\.".equals(l.get(j))) {
            j++;
            if (j < l.size() && "\\d+".equals(l.get(j))) {
                l.set(i, "\\d+\\.\\d+");
                indexesToBeRemoved.add(j);
                indexesToBeRemoved.add(--j);
            }
        }

    }
}

for (int i : indexesToBeRemoved) {
    l.remove(i);
}

System.out.println(l.toString());

O/P:
[(?i), \d+, \., \d+, (?i), \d+, \.]
[(?i), \d+\.\d+, (?i), \d+, \.]

The List.subList is your friend, use it.

 List<String> pattern = Arrays.asList("\\d+", "\\.", "\\d+");
 for(int i=0; i<=l.size()-pattern.size(); i++) {
     List<String> subList = l.subList(i, i+pattern.size());
     if(subList.equals(pattern)) {
         subList.clear();
         subList.add("\\d+\\.\\d+");
     }
 }
 System.out.println(l);

If you are tied to using a LinkedList, you want to use an iterator rather than indexing, because get(n) is a O(n) operation. Since you want to be able to go backwards, you have to get a ListIterator from the listIterator() function.

for(ListIterator<String> i = l.listIterator(); i.hasNext();){
    String element = i.next();
    if(element.equals("\\d+") && i.hasNext()) {
       if(i.next().equals("\\.") && i.hasNext()) {
           if(i.next().equals("\\d+")) {
               i.remove();
               i.previous();
               i.remove();
               i.previous();
               i.set("\\d+\\.\\d+");
           } else {
               i.previous();
               i.previous();
           }
        } else {
            i.previous();
        }
    }
}

This can probably be cleaned up and made more general, but ListIterator is the tool you should use when working with linked lists.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM