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

Last change on this file since 13795 was 12909, checked in by Don-vip, 7 years ago

see #15361 - add more debug info + update licence information

  • Property svn:eol-style set to native
File size: 5.4 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 * Released under the MIT License - https://opensource.org/licenses/MIT
12 *
13 * Copyright 2007-2017 David Koelle
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining
16 * a copy of this software and associated documentation files (the "Software"),
17 * to deal in the Software without restriction, including without limitation
18 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19 * and/or sell copies of the Software, and to permit persons to whom the
20 * Software is furnished to do so, subject to the following conditions:
21 *
22 * The above copyright notice and this permission notice shall be included
23 * in all copies or substantial portions of the Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
29 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
30 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
31 * USE OR OTHER DEALINGS IN THE SOFTWARE.
32 */
33import java.io.Serializable;
34import java.text.Collator;
35import java.util.Comparator;
36import java.util.Locale;
37
38/**
39 * The Alphanum Algorithm is an improved sorting algorithm for strings
40 * containing numbers: Instead of sorting numbers in ASCII order like a standard
41 * sort, this algorithm sorts numbers in numeric order.
42 *
43 * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
44 *
45 * This is an updated version with enhancements made by Daniel Migowski, Andre
46 * Bogus, David Koelle and others.
47 *
48 */
49public final class AlphanumComparator implements Comparator<String>, Serializable {
50
51 private static final long serialVersionUID = 1L;
52
53 private static final AlphanumComparator INSTANCE = new AlphanumComparator();
54
55 /**
56 * Replies the unique instance.
57 * @return the unique instance
58 */
59 public static AlphanumComparator getInstance() {
60 return INSTANCE;
61 }
62
63 /**
64 * Constructs a new Alphanum Comparator.
65 */
66 private AlphanumComparator() {
67 }
68
69 /**
70 * Returns an alphanum chunk.
71 * Length of string is passed in for improved efficiency (only need to calculate it once).
72 * @param s string
73 * @param slength string length
74 * @param marker position
75 * @return alphanum chunk found at given position
76 */
77 private static String getChunk(String s, int slength, int marker) {
78 StringBuilder chunk = new StringBuilder();
79 char c = s.charAt(marker);
80 chunk.append(c);
81 marker++;
82 if (Character.isDigit(c)) {
83 while (marker < slength) {
84 c = s.charAt(marker);
85 if (!Character.isDigit(c)) {
86 break;
87 }
88 chunk.append(c);
89 marker++;
90 }
91 } else {
92 while (marker < slength) {
93 c = s.charAt(marker);
94 if (Character.isDigit(c)) {
95 break;
96 }
97 chunk.append(c);
98 marker++;
99 }
100 }
101 return chunk.toString();
102 }
103
104 @Override
105 public int compare(String s1, String s2) {
106 if (s1 == null && s2 == null) {
107 return 0;
108 } else if (s1 == null) {
109 return -1;
110 } else if (s2 == null) {
111 return 1;
112 }
113
114 int thisMarker = 0;
115 int thatMarker = 0;
116 int s1Length = s1.length();
117 int s2Length = s2.length();
118
119 while (thisMarker < s1Length && thatMarker < s2Length) {
120 String thisChunk = getChunk(s1, s1Length, thisMarker);
121 thisMarker += thisChunk.length();
122
123 String thatChunk = getChunk(s2, s2Length, thatMarker);
124 thatMarker += thatChunk.length();
125
126 // If both chunks contain numeric characters, sort them numerically
127 int result;
128 if (Character.isDigit(thisChunk.charAt(0)) && Character.isDigit(thatChunk.charAt(0))) {
129 // Simple chunk comparison by length.
130 int thisChunkLength = thisChunk.length();
131 result = thisChunkLength - thatChunk.length();
132 // If equal, the first different number counts
133 if (result == 0) {
134 for (int i = 0; i < thisChunkLength; i++) {
135 result = thisChunk.charAt(i) - thatChunk.charAt(i);
136 if (result != 0) {
137 return result;
138 }
139 }
140 }
141 } else {
142 // Instantiate the collator
143 Collator compareOperator = Collator.getInstance(Locale.getDefault());
144 // Compare regardless of accented letters
145 compareOperator.setStrength(Collator.SECONDARY);
146 result = compareOperator.compare(thisChunk, thatChunk);
147 }
148
149 if (result != 0) {
150 return result;
151 }
152 }
153
154 return s1Length - s2Length;
155 }
156}
Note: See TracBrowser for help on using the repository browser.