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

Last change on this file since 12321 was 8928, checked in by Don-vip, 8 years ago

javadoc fixes

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