How to lowercase every element of a collection efficiently?

后端 未结 11 547
走了就别回头了
走了就别回头了 2020-12-02 16:53

What\'s the most efficient way to lower case every element of a List or Set?

My idea for a List:

final List strings = new ArrayList<         


        
相关标签:
11条回答
  • 2020-12-02 17:22

    Well, there is no real elegant solution due to two facts:

    • Strings in Java are immutable
    • Java gives you no real nice map(f, list) function as you have in functional languages.

    Asymptotically speaking, you can't get a better run time than your current method. You will have to create a new string using toLowerCase() and you will need to iterate by yourself over the list and generate each new lower-case string, replacing it with the existing one.

    0 讨论(0)
  • 2020-12-02 17:22

    If you are fine with changing the input list here is one more way to achieve it.

    strings.replaceAll(String::toLowerCase)

    0 讨论(0)
  • 2020-12-02 17:33

    I don't believe it is possible to do the manipulation in place (without creating another Collection) if you change strings to be a Set. This is because you can only iterate over the Set using an iterator or a for each loop, and cannot insert new objects whilst doing so (it throws an exception)

    0 讨论(0)
  • 2020-12-02 17:38

    You can do this with Google Collections:

        Collection<String> lowerCaseStrings = Collections2.transform(strings,
            new Function<String, String>() {
                public String apply(String str) {
                    return str.toLowerCase();
                }
            }
        );
    
    0 讨论(0)
  • 2020-12-02 17:40

    Referring to the ListIterator method in the accepted (Matthew T. Staebler's) solution. How is using the ListIterator better than the method here?

    public static Set<String> replace(List<String> strings) {
        Set<String> set = new HashSet<>();
        for (String s: strings)
            set.add(s.toLowerCase());
        return set;
    }
    
    0 讨论(0)
  • 2020-12-02 17:41

    This seems like a fairly clean solution for lists. It should allow for the particular List implementation being used to provide an implementation that is optimal for both the traversal of the list--in linear time--and the replacing of the string--in constant time.

    public static void replace(List<String> strings)
    {
        ListIterator<String> iterator = strings.listIterator();
        while (iterator.hasNext())
        {
            iterator.set(iterator.next().toLowerCase());
        }
    }
    

    This is the best that I can come up with for sets. As others have said, the operation cannot be performed in-place in the set for a number of reasons. The lower-case string may need to be placed in a different location in the set than the string it is replacing. Moreover, the lower-case string may not be added to the set at all if it is identical to another lower-case string that has already been added (e.g., "HELLO" and "Hello" will both yield "hello", which will only be added to the set once).

    public static void replace(Set<String> strings)
    {
        String[] stringsArray = strings.toArray(new String[0]);
        for (int i=0; i<stringsArray.length; ++i)
        {
            stringsArray[i] = stringsArray[i].toLowerCase();
        }
        strings.clear();
        strings.addAll(Arrays.asList(stringsArray));
    }
    
    0 讨论(0)
提交回复
热议问题