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

Last change on this file since 8574 was 8419, checked in by Don-vip, 9 years ago

Sonar: various code style cleanup:

  • fix copyright
  • classes that should be final
  • order of javadoc At-clauses
  • unexpected spaces before parenthesis
  • Property svn:eol-style set to native
File size: 4.8 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 * Length of string is passed in for improved efficiency (only need to
64 * calculate it once) *
65 */
66 private String getChunk(String s, int slength, int marker) {
67 StringBuilder chunk = new StringBuilder();
68 char c = s.charAt(marker);
69 chunk.append(c);
70 marker++;
71 if (Character.isDigit(c)) {
72 while (marker < slength) {
73 c = s.charAt(marker);
74 if (!Character.isDigit(c)) {
75 break;
76 }
77 chunk.append(c);
78 marker++;
79 }
80 } else {
81 while (marker < slength) {
82 c = s.charAt(marker);
83 if (Character.isDigit(c)) {
84 break;
85 }
86 chunk.append(c);
87 marker++;
88 }
89 }
90 return chunk.toString();
91 }
92
93 @Override
94 public int compare(String s1, String s2) {
95 if (s1 == null && s2 == null) {
96 return 0;
97 } else if (s1 == null) {
98 return -1;
99 } else if (s2 == null) {
100 return 1;
101 }
102
103 int thisMarker = 0;
104 int thatMarker = 0;
105 int s1Length = s1.length();
106 int s2Length = s2.length();
107
108 while (thisMarker < s1Length && thatMarker < s2Length) {
109 String thisChunk = getChunk(s1, s1Length, thisMarker);
110 thisMarker += thisChunk.length();
111
112 String thatChunk = getChunk(s2, s2Length, thatMarker);
113 thatMarker += thatChunk.length();
114
115 // If both chunks contain numeric characters, sort them numerically
116 int result;
117 if (Character.isDigit(thisChunk.charAt(0)) && Character.isDigit(thatChunk.charAt(0))) {
118 // Simple chunk comparison by length.
119 int thisChunkLength = thisChunk.length();
120 result = thisChunkLength - thatChunk.length();
121 // If equal, the first different number counts
122 if (result == 0) {
123 for (int i = 0; i < thisChunkLength; i++) {
124 result = thisChunk.charAt(i) - thatChunk.charAt(i);
125 if (result != 0) {
126 return result;
127 }
128 }
129 }
130 } else {
131 // Instantiate the collator
132 Collator compareOperator = Collator.getInstance(Locale.getDefault());
133 // Compare regardless of accented letters
134 compareOperator.setStrength(Collator.SECONDARY);
135 result = compareOperator.compare(thisChunk, thatChunk);
136 }
137
138 if (result != 0) {
139 return result;
140 }
141 }
142
143 return s1Length - s2Length;
144 }
145}
Note: See TracBrowser for help on using the repository browser.