Java 如何有效地小写集合的每个元素?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2644637/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 10:17:33  来源:igfitidea点击:

How to lowercase every element of a collection efficiently?

javastring

提问by Chris

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

小写 List 或 Set 的每个元素的最有效方法是什么?

My idea for a List:

我对列表的想法:

final List<String> strings = new ArrayList<String>();
strings.add("HELLO");
strings.add("WORLD");

for(int i=0,l=strings.size();i<l;++i)
{
  strings.add(strings.remove(0).toLowerCase());
}

Is there a better, faster way? How would this example look like for a Set? As there is currently no method for applying an operation to each element of a Set (or List) can it be done without creating an additional temporary Set?

有没有更好更快的方法?这个例子对于 Set 会是什么样子?由于目前没有将操作应用于 Set(或 List)的每个元素的方法,是否可以在不创建额外的临时 Set 的情况下完成?

Something like this would be nice:

这样的事情会很好:

Set<String> strings = new HashSet<String>();
strings.apply(
  function (element)
  { this.replace(element, element.toLowerCase();) } 
);

Thanks,

谢谢,

采纳答案by Matthew T. Staebler

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.

对于列表,这似乎是一个相当干净的解决方案。它应该允许使用特定的 List 实现来提供对于列表的遍历(线性时间)和字符串的替换(恒定时间)都是最佳的实现。

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).

这是我能想到的最好的集合。正如其他人所说,由于多种原因,无法在集合中就地执行操作。小写字符串可能需要放置在集合中与它替换的字符串不同的位置。此外,如果小写字符串与已经添加的另一个小写字符串相同(例如,“HELLO”和“Hello”都会产生“hello”,这将只能添加到集合中一次)。

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));
}

回答by Maurice Perry

This is probably faster:

这可能更快:

for(int i=0,l=strings.size();i<l;++i)
{
  strings.set(i, strings.get(i).toLowerCase());
}

回答by Yuval Adam

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.
  • StringJava 中的 s 是不可变的
  • Java 没有map(f, list)像函数式语言那样为您提供真正好的功能。

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.

渐近地说,您无法获得比当前方法更好的运行时间。您必须使用创建一个新字符串,toLowerCase()并且需要自己遍历列表并生成每个新的小写字符串,并将其替换为现有字符串。

回答by thSoft

Try CollectionUtils#transform in Commons Collectionsfor an in-place solution, or Collections2#transform in Guavaif you need a live view.

如果需要实时视图,请在 Commons Collections 中尝试CollectionUtils#transform 以获得就地解决方案,或在 Guava 中尝试Collections2#transform

回答by Tarski

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)

如果您将字符串更改为 Set,我认为不可能就地进行操作(无需创建另一个集合)。这是因为您只能使用迭代器或 for each 循环遍历 Set,并且在这样做时不能插入新对象(它会引发异常)

回答by Roman

You can do this with Google Collections:

您可以使用 Google Collections 执行此操作:

    Collection<String> lowerCaseStrings = Collections2.transform(strings,
        new Function<String, String>() {
            public String apply(String str) {
                return str.toLowerCase();
            }
        }
    );

回答by leba-lev

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

参考已接受(Matthew T. Staebler 的)解决方案中的 ListIterator 方法。如何使用 ListIterator 比这里的方法更好?

public static Set<String> replace(List<String> strings) {
    Set<String> set = new HashSet<>();
    for (String s: strings)
        set.add(s.toLowerCase());
    return set;
}

回答by Igor G.

Yet another solution, but with Java 8 and above:

另一个解决方案,但使用 Java 8 及更高版本:

List<String> result = strings.stream()
                             .map(String::toLowerCase)
                             .collect(Collectors.toList());

回答by NIKHIL CHAURASIA

I was looking for similar stuff, but was stuck because my ArrayListobject was not declared as GENERICand it was available as raw Listtype object from somewhere. I was just getting an ArrayListobject "_products". So, what I did is mentioned below and it worked for me perfectly ::

我正在寻找类似的东西,但被卡住了,因为我的ArrayList对象没有声明为GENERIC并且它可以从某个地方作为原始List类型对象使用。我刚刚得到一个ArrayList对象“_products”。所以,下面提到了我所做的,它对我来说非常有效::

List<String> dbProducts = _products;
    for(int i = 0; i<dbProducts.size(); i++) {
        dbProducts.add(dbProducts.get(i).toLowerCase());         
    }

That is, I first took my available _productsand made a GENERIClist object (As I were getting only strings in same) then I applied the toLowerCase()method on list elements which was not working previously because of non-generic ArrayListobject.

也就是说,我首先使用可用的_products并创建了一个GENERIC列表对象(因为我只得到相同的字符串)然后我在列表元素上应用了toLowerCase()方法,该方法以前由于非通用ArrayList对象而不起作用。

And the method toLowerCase()we are using here is of Stringclass.

我们在这里使用的toLowerCase()方法是String类。

String java.lang.String.toLowerCase()

字符串 java.lang.String.toLowerCase()

not of ArrayListor Objectclass.

不是ArrayListObject类。

Please correct if m wrong. Newbie in JAVA seeks guidance. :)

如果我错了,请纠正。JAVA新手求指点。:)

回答by Ankur Gupta

Using JAVA 8 parallel stream it becomes faster

使用 JAVA 8 并行流它变得更快

List<String> output= new ArrayList<>();
List<String> input= new ArrayList<>();
input.add("A");
input.add("B");
input.add("C");
input.add("D");
input.stream().parallel().map((item) -> item.toLowerCase())
            .collect(Collectors.toCollection(() -> output));