当前位置:  开发笔记 > 编程语言 > 正文

Java中的自然排序顺序字符串比较 - 是内置的吗?

如何解决《Java中的自然排序顺序字符串比较-是内置的吗?》经验,为你挑选了4个好方法。

我想要一些保留自然排序顺序1的字符串比较函数.Java中是否有这样的内容?我在String类中找不到任何内容,而Comparator类只知道两个实现.

我可以自己动手(这不是一个非常难的问题),但如果我不需要,我宁愿不重新发明轮子.

在我的具体情况下,我有我想要排序的软件版本字符串.所以我希望"1.2.10.5"被认为大于"1.2.9.1".


1通过"自然"排序顺序,我的意思是它将字符串与人类比较它们的方式进行比较,而不是"ascii-betical"排序顺序只对程序员有意义.换句话说,"image9.jpg"小于"image10.jpg","album1set2page9photo1.jpg"小于"album1set2page10photo5.jpg","1.2.9.1"小于"1.2.10.5"



1> OscarRyz..:

在java中,"自然"顺序含义是"词典"顺序,因此核心中没有像您正在寻找的那样实现.

有开源实现.

这是一个:

NaturalOrderComparator.java

请务必阅读:

Cougaar开源许可证

我希望这有帮助!


在选择像这样的开源实现时,您应确保它们完全符合您的预期.许多人专注于提供在用户界面中看起来直观且漂亮的订单.有时他们接受并跳过空格,跳过前导零,最重要的是在较长的字符串之前放置较短的字符串,当它们相等时.然后将字符串1.020放在1.20之后.如果您使用它来确定两个版本是否相等,则在这种情况下可能会出现误报.即检查compareTo()返回0时.

2> Mikhail..:

我测试了其他人在这里提到的三个Java实现,发现他们的工作略有不同,但没有像我期望的那样.

无论AlphaNumericStringComparator和AlphanumComparator,这样才不会忽略空格pic2之前放置pic 1.

在另一方面NaturalOrderComparator忽略不仅空格也是所有前导零,以便sig[1]先于sig[0].

关于性能AlphaNumericStringComparator比其他两个慢~x10.



3> Yishai..:

String实现了Comparable,这就是Java中的自然顺序(使用类似的接口进行比较).您可以将字符串放在TreeSet中,也可以使用Collections或Arrays类进行排序.

但是,在您的情况下,您不希望"自然排序",您真的需要一个自定义比较器,然后您可以在Collections.sort方法或带有比较器的Arrays.sort方法中使用它.

就你想要在比较器中实现的特定逻辑而言(由点分隔的数字)我不知道任何现有的标准实现,但正如你所说,这不是一个难题.

编辑:在你的评论中,你的链接让你在这里,如果你不介意它是区分大小写的事实,这是一个体面的工作.这是修改后的代码,允许您传入String.CASE_INSENSITIVE_ORDER:

    /*
     * The Alphanum Algorithm is an improved sorting algorithm for strings
     * containing numbers.  Instead of sorting numbers in ASCII order like
     * a standard sort, this algorithm sorts numbers in numeric order.
     *
     * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
     *
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or any later version.
     *
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with this library; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     *
     */

    import java.util.Comparator;

    /**
     * This is an updated version with enhancements made by Daniel Migowski,
     * Andre Bogus, and David Koelle
     *
     * To convert to use Templates (Java 1.5+):
     *   - Change "implements Comparator" to "implements Comparator"
     *   - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"
     *   - Remove the type checking and casting in compare().
     *
     * To use this class:
     *   Use the static "sort" method from the java.util.Collections class:
     *   Collections.sort(your list, new AlphanumComparator());
     */
    public class AlphanumComparator implements Comparator
    {
        private Comparator comparator = new NaturalComparator();

        public AlphanumComparator(Comparator comparator) {
            this.comparator = comparator;
        }

        public AlphanumComparator() {

        }

        private final boolean isDigit(char ch)
        {
            return ch >= 48 && ch <= 57;
        }

        /** Length of string is passed in for improved efficiency (only need to calculate it once) **/
        private final String getChunk(String s, int slength, int marker)
        {
            StringBuilder chunk = new StringBuilder();
            char c = s.charAt(marker);
            chunk.append(c);
            marker++;
            if (isDigit(c))
            {
                while (marker < slength)
                {
                    c = s.charAt(marker);
                    if (!isDigit(c))
                        break;
                    chunk.append(c);
                    marker++;
                }
            } else
            {
                while (marker < slength)
                {
                    c = s.charAt(marker);
                    if (isDigit(c))
                        break;
                    chunk.append(c);
                    marker++;
                }
            }
            return chunk.toString();
        }

        public int compare(String s1, String s2)
        {

            int thisMarker = 0;
            int thatMarker = 0;
            int s1Length = s1.length();
            int s2Length = s2.length();

            while (thisMarker < s1Length && thatMarker < s2Length)
            {
                String thisChunk = getChunk(s1, s1Length, thisMarker);
                thisMarker += thisChunk.length();

                String thatChunk = getChunk(s2, s2Length, thatMarker);
                thatMarker += thatChunk.length();

                // If both chunks contain numeric characters, sort them numerically
                int result = 0;
                if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
                {
                    // Simple chunk comparison by length.
                    int thisChunkLength = thisChunk.length();
                    result = thisChunkLength - thatChunk.length();
                    // If equal, the first different number counts
                    if (result == 0)
                    {
                        for (int i = 0; i < thisChunkLength; i++)
                        {
                            result = thisChunk.charAt(i) - thatChunk.charAt(i);
                            if (result != 0)
                            {
                                return result;
                            }
                        }
                    }
                } else
                {
                    result = comparator.compare(thisChunk, thatChunk);
                }

                if (result != 0)
                    return result;
            }

            return s1Length - s2Length;
        }

        private static class NaturalComparator implements Comparator {
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        }
    }


"自然排序"是将"image9.jpg"排序为小于"image10.jpg"的广泛使用的术语.它是"自然的",因为它是人类如何对它们进行排序,而不是默认情况下计算机进行的非自然的"ascii-betical"排序.http://www.codinghorror.com/blog/archives/001018.html

4> Panayotis..:

看看这个实现.它应该尽可能快,没有任何正则表达式或数组操作或方法调用,只有几个标志和很多情况.

这应该对字符串内的任何数字组合进行排序,并正确支持相等的数字并继续前进.

public static int naturalCompare(String a, String b, boolean ignoreCase) {
    if (ignoreCase) {
        a = a.toLowerCase();
        b = b.toLowerCase();
    }
    int aLength = a.length();
    int bLength = b.length();
    int minSize = Math.min(aLength, bLength);
    char aChar, bChar;
    boolean aNumber, bNumber;
    boolean asNumeric = false;
    int lastNumericCompare = 0;
    for (int i = 0; i < minSize; i++) {
        aChar = a.charAt(i);
        bChar = b.charAt(i);
        aNumber = aChar >= '0' && aChar <= '9';
        bNumber = bChar >= '0' && bChar <= '9';
        if (asNumeric)
            if (aNumber && bNumber) {
                if (lastNumericCompare == 0)
                    lastNumericCompare = aChar - bChar;
            } else if (aNumber)
                return 1;
            else if (bNumber)
                return -1;
            else if (lastNumericCompare == 0) {
                if (aChar != bChar)
                    return aChar - bChar;
                asNumeric = false;
            } else
                return lastNumericCompare;
        else if (aNumber && bNumber) {
            asNumeric = true;
            if (lastNumericCompare == 0)
                lastNumericCompare = aChar - bChar;
        } else if (aChar != bChar)
            return aChar - bChar;
    }
    if (asNumeric)
        if (aLength > bLength && a.charAt(bLength) >= '0' && a.charAt(bLength) <= '9') // as number
            return 1;  // a has bigger size, thus b is smaller
        else if (bLength > aLength && b.charAt(aLength) >= '0' && b.charAt(aLength) <= '9') // as number
            return -1;  // b has bigger size, thus a is smaller
        else if (lastNumericCompare == 0)
          return aLength - bLength;
        else
            return lastNumericCompare;
    else
        return aLength - bLength;
}

推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有