source: josm/trunk/src/org/openstreetmap/josm/tools/AlphanumComparator.java@ 5508

Last change on this file since 5508 was 5087, checked in by simon04, 12 years ago

fix #7507 - NullPointerException in AlphanumComparator

File size: 4.0 KB
Line 
1package org.openstreetmap.josm.tools;
2
3/*
4 * The Alphanum Algorithm is an improved sorting algorithm for strings
5 * containing numbers. Instead of sorting numbers in ASCII order like a standard
6 * sort, this algorithm sorts numbers in numeric order.
7 *
8 * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
9 *
10 *
11 * This library is free software; you can redistribute it and/or modify it under
12 * the terms of the GNU Lesser General Public License as published by the Free
13 * Software Foundation; either version 2.1 of the License, or any later version.
14 *
15 * This library is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 * details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this library; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25import java.util.Comparator;
26
27/**
28 * The Alphanum Algorithm is an improved sorting algorithm for strings
29 * containing numbers: Instead of sorting numbers in ASCII order like a standard
30 * sort, this algorithm sorts numbers in numeric order.
31 *
32 * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
33 *
34 * This is an updated version with enhancements made by Daniel Migowski, Andre
35 * Bogus, and David Koelle.
36 *
37 */
38public class AlphanumComparator implements Comparator<String> {
39
40 /**
41 * Length of string is passed in for improved efficiency (only need to
42 * calculate it once) *
43 */
44 private String getChunk(String s, int slength, int marker) {
45 StringBuilder chunk = new StringBuilder();
46 char c = s.charAt(marker);
47 chunk.append(c);
48 marker++;
49 if (Character.isDigit(c)) {
50 while (marker < slength) {
51 c = s.charAt(marker);
52 if (!Character.isDigit(c)) {
53 break;
54 }
55 chunk.append(c);
56 marker++;
57 }
58 } else {
59 while (marker < slength) {
60 c = s.charAt(marker);
61 if (Character.isDigit(c)) {
62 break;
63 }
64 chunk.append(c);
65 marker++;
66 }
67 }
68 return chunk.toString();
69 }
70
71 @Override
72 public int compare(String s1, String s2) {
73 if (s1 == null && s2 == null) {
74 return 0;
75 } else if (s1 == null) {
76 return -1;
77 } else if (s2 == null) {
78 return 1;
79 }
80
81 int thisMarker = 0;
82 int thatMarker = 0;
83 int s1Length = s1.length();
84 int s2Length = s2.length();
85
86 while (thisMarker < s1Length && thatMarker < s2Length) {
87 String thisChunk = getChunk(s1, s1Length, thisMarker);
88 thisMarker += thisChunk.length();
89
90 String thatChunk = getChunk(s2, s2Length, thatMarker);
91 thatMarker += thatChunk.length();
92
93 // If both chunks contain numeric characters, sort them numerically
94 int result;
95 if (Character.isDigit(thisChunk.charAt(0)) && Character.isDigit(thatChunk.charAt(0))) {
96 // Simple chunk comparison by length.
97 int thisChunkLength = thisChunk.length();
98 result = thisChunkLength - thatChunk.length();
99 // If equal, the first different number counts
100 if (result == 0) {
101 for (int i = 0; i < thisChunkLength; i++) {
102 result = thisChunk.charAt(i) - thatChunk.charAt(i);
103 if (result != 0) {
104 return result;
105 }
106 }
107 }
108 } else {
109 result = thisChunk.compareTo(thatChunk);
110 }
111
112 if (result != 0) {
113 return result;
114 }
115 }
116
117 return s1Length - s2Length;
118 }
119}
Note: See TracBrowser for help on using the repository browser.