ulquiorra
ulquiorra

Reputation: 945

compare elements in a listIterator

I have a simple list of books like this

        mItems.add("Steve Jobs");
        mItems.add("Inheritance (The Inheritance Cycle)");
        mItems.add("The Hunger Games");
        mItems.add("The LEGO Ideas Book");
        mItems.add("Catching Fire (The Second Book of the Hunger Games)");
        mItems.add("Death Comes to Pemberley");
        mItems.add("Diary of a Wimpy Kid 6: Cabin Fever");
        mItems.add("Explosive Eighteen: A Stephanie Plum Novel");
        mItems.add("Elder Scrolls V: Skyrim: Prima Official Game Guide");

I want to reorganize the list alphabetically by adding a header when the next book start with a different letter

So the final list should be like this

Etc...

Obviously I need to compare next and previous item so I used a ListIterator

mItems = new ArrayList<String>();
        mItems.add("Steve Jobs");
        mItems.add("Inheritance (The Inheritance Cycle)");
        mItems.add("The Hunger Games");
        mItems.add("The LEGO Ideas Book");
        mItems.add("Catching Fire (The Second Book of the Hunger Games)");
        mItems.add("Death Comes to Pemberley");
        mItems.add("Diary of a Wimpy Kid 6: Cabin Fever");
        mItems.add("Explosive Eighteen: A Stephanie Plum Novel");
        mItems.add("Elder Scrolls V: Skyrim: Prima Official Game Guide");
        Collections.sort(mItems);

        ArrayList<Book> books= new ArrayList<Book>();
        int position = 0;
        boolean isSeparator = false;
        ListIterator<String> it = mItems.listIterator();

        while(it.hasNext()) {
            isSeparator = false;

            String name = it.next();

            char[] nameArray;

            // If it is the first item then need a separator
            if (position == 0) {
                isSeparator = true;
                nameArray = name.toCharArray();
            }
            else {
                // Get the previous book's name
                String previousName =  it.previous();

                // Convert the previous and current book names
                // into char arrays
                char[] previousNameArray = previousName.toCharArray();
                nameArray = name.toCharArray();

                // Compare the first character of previous book and current book,
                if (nameArray[0] != previousNameArray[0]) {
                    isSeparator = true;
                }


                // go next item
                it.next();
            }

           // item is a separator
            if (isSeparator) {
                Book book= new Contact(String.valueOf(nameArray[0]), null, isSeparator);
                books.add( book);
            }

            // Create a Book object to store the name and if it's a separator or not
            Book book= new Book (name, null, false);
            books.add( book);

            position++;
        }

The problem is that Iterator doesn't work in that way because next() and previous() method jump in the next/previous iteration. They don't get the next/previous value while staying in same iteration

Any advices ? Thank you very much

Upvotes: 0

Views: 1611

Answers (5)

OldCurmudgeon
OldCurmudgeon

Reputation: 65851

If you wrap your sorted list in an Iterable you can add the extra sections yourself.

private static class InitialedList implements Iterable<String> {

    final List<String> items;

    public InitialedList(List<String> mItems) {
        this.items = mItems;
    }

    @Override
    public Iterator<String> iterator() {
        return new Iterator<String>() {
            Iterator<String> i = items.iterator();
            // The next from the list.
            String next = null;
            // The last one we delivered.
            String last = null;

            @Override
            public boolean hasNext() {
                return next != null || i.hasNext();
            }

            @Override
            public String next() {
                // Peek at the next.
                if (next == null) {
                    next = i.next();
                }
                // What to return.
                String it = null;
                // Is there a change in initial?
                if (next != null) {
                    // Behaviour undefined if empty string in list.
                    if (last == null || last.charAt(0) != next.charAt(0)) {
                        it = next.substring(0, 1);
                    } else {
                        it = next;
                        next = null;
                    }
                }
                return last = it;
            }

        };
    }
}

public void test() {
    List<String> mItems = new ArrayList<>();
    mItems.add("Steve Jobs");
    mItems.add("Inheritance (The Inheritance Cycle)");
    mItems.add("The Hunger Games");
    mItems.add("The LEGO Ideas Book");
    mItems.add("Catching Fire (The Second Book of the Hunger Games)");
    mItems.add("Death Comes to Pemberley");
    mItems.add("Diary of a Wimpy Kid 6: Cabin Fever");
    mItems.add("Explosive Eighteen: A Stephanie Plum Novel");
    mItems.add("Elder Scrolls V: Skyrim: Prima Official Game Guide");
    Collections.sort(mItems);
    for (String s : new InitialedList(mItems)) {
        System.out.println(s);
    }
}

prints:

C
Catching Fire (The Second Book of the Hunger Games)
D
Death Comes to Pemberley
Diary of a Wimpy Kid 6: Cabin Fever
E
Elder Scrolls V: Skyrim: Prima Official Game Guide
Explosive Eighteen: A Stephanie Plum Novel
I
Inheritance (The Inheritance Cycle)
S
Steve Jobs
T
The Hunger Games
The LEGO Ideas Book

Upvotes: 1

Alex Derkach
Alex Derkach

Reputation: 769

If you're using java 8:

List<String> newItems = mItems.stream()
    .flatMap(s -> Stream.of(s.substring(0, 1), s))
    .distinct()
    .sorted()
    .collect(toList());

Now newItems contains the following:

C
Catching Fire (The Second Book of the Hunger Games)
D
Death Comes to Pemberley
Diary of a Wimpy Kid 6: Cabin Fever
E
Explosive Eighteen: A Stephanie Plum Novel
Elder Scrolls V: Skyrim: Prima Official Game Guide
I
Inheritance (The Inheritance Cycle)
S
Steve Jobs
T
The Hunger Games
The LEGO Ideas Book

Upvotes: 1

Nikitha
Nikitha

Reputation: 373

    ListIterator<String> it = mItems.listIterator();
    int i = 0;
    String [] listOfFirstChars = new String[26];
    int indexForAddingCharacter = 0;
    while(it.hasNext()) {              
          String firstChar = it.next().subString(0,1);
          if(firstChar != listOfFirstChars[indexForAddingCharacter]){
          listOfFirstChars[indexForAddingCharacter] = firstChar;
          indexForAddingCharacter++;
          mItems.add(i, firstChar);
          }
    i++;                 
    }

Let me know if this works :)

Upvotes: 0

gentooise
gentooise

Reputation: 431

Simply store and compare previous and current element:

String prev = null;
String curr = null;
char c;
while(it.hasNext()) {
    curr = it.next();
    if (prev == null || prev.charAt(0) != curr.charAt(0)) {
        c = curr.charAt(0);
    }

    // Do what you need to do with current name 'curr' and initial character 'c'

    prev = curr;
}

Upvotes: 0

Jean Logeart
Jean Logeart

Reputation: 53839

Get all the initials, add them to the list, and sort:

Set<String> initials = new HashSet<>();
for(String title: mItems) {
    initials.add(title.substring(0, 1));
}
mItems.addAll(initials);
Collections.sort(mItems);

Upvotes: 2

Related Questions