Reputation: 945
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
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
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
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
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
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