我有一个String[],值如下:
1
| public static final String[] VALUES = new String[] {"AB", "BC", "CD", "AE"}; |
考虑到String s,有没有一个很好的方法来测试VALUES是否含有s?
- 很长一段时间,但是可以使用for循环:"for(string s:values)if(s.equals("myvalue")返回true;
- 是的,我几乎不好意思问这个问题,但同时也很惊讶没人问这个问题。这是我从未接触过的那些API之一…
- @卡米克。对于你的问题,我否决了这个问题和你的答案-现在-因为它为我节省了30分钟和20行代码,为循环写得很难看-现在-。三年前没读过。(顺便说一句,谢谢:)
- @卡米克——我和这个有一个几乎相同的情况:stackoverflow.com/a/223929/12943它只是不断获得选票,但它只是Sun文档中的一个拷贝/粘贴。我想得分是基于你提供了多少帮助,而不是你投入了多少努力——主要是你发布它的速度!也许我们偶然发现了约翰·斯基特的秘密!好的答案,给你+1。
- 如果您使用的是ApacheCommons,那么org.apache.commons.lang.arrayutils.contains()可以为您实现这一点。
- @扎克:你掉进了反模式的陷阱,如果是反模式,就不要这样做。
- @卡米克是因为人们,像我一样,用谷歌搜索一个问题,点击"所以"结果,查看你的答案,测试它,它工作,向上投票,然后离开。
1
| Arrays. asList(yourArray ). contains(yourValue ) |
警告:这不适用于基元数组(请参见注释)。
从Java-8开始,您现在可以使用流。
1 2
| String[] values = {"AB", "BC", "CD", "AE"};
boolean contains = Arrays. stream(values ). anyMatch("s"::equals ); |
为了检查int、double或long的数组是否包含值,请分别使用IntStream、DoubleStream或LongStream。
例子
1 2
| int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4); |
- 我对数组类中的搜索函数的性能有点好奇,而不是迭代数组并使用equals()函数或==作为基元。
- 它们都是线性搜索。
- @托马斯:我认为aslist()实际上可能会分配一个新的对象来委托给现有的数组,所以您要支付分配成本。列表由数组支持,因此不应重新分配元素本身。
- 您不会损失太多,因为aslist()返回一个以数组为中心的arraylist。构造函数只会更改一个引用,这样就不需要在那里做太多的工作。并且contains()/indexof()将迭代并使用equals()。不过,对于原语,最好自己编写代码。对于字符串或其他类,差异将不明显。
- 对于基元数组,Array.asList方法非常快速。;)
- 奇怪的是,NetBeans声称"int[]holidays"的"array.aslist(holidays)"返回"list",而不是"list"。它只包含一个元素。这意味着contains不起作用,因为它只有一个元素:int数组。
- 这个方法比基本的for搜索循环慢3倍
- 尼尔古兹:事实上,这对原始人不起作用。在Java中,原始类型不能是泛型的。as list被声明为listas list(t…)。当向其中传递int[]时,编译器将推断t=int[],因为它无法推断t=int,因为基元不能是泛型的。
- @乔伊只是一个旁注,它是一个ArrayList,但不是你所期望的java.util.ArrayList,返回的真正类是:java.util.Arrays.ArrayList,定义为:public class java.util.Arrays {private static class ArrayList ... {}}。
- EEK。为什么它是另一个数组列表?O.O
- @?因为它不是一个"普通"的array list,arrays.aslist(t…)返回一个由指定数组支持的固定大小的列表。"arrays.array list只是一个围绕现有数组的"瘦"列表包装器。最重要的是,不能添加或删除元素,因为它不分配自己的数组,而是直接使用原始数组。这使得它的使用非常便宜,因为不需要复制,它只存储对原始数组的引用。所以不要害怕使用数组。
- @你写的Joey"构造器只会改变一个引用,所以在那里不需要做太多的工作"。哪个建造师?
- @洛克,完全同意,2年前我质疑所有上升的选票,当时它只有75票。任何答案都应该限制在10左右。答案不应在人气竞赛中使用,只应表明这是OP应考虑解决给定问题的答案。
- 上票有什么问题?它节省了一些人的时间,更好奇的人阅读评论,了解更多,因此在未来做出更好的决定。对我来说,这是一个成功的答案。
- @天哪,这是我的答案。从上面阅读我的评论。任何答案都不可能那么好。一个有700张赞成票的问题和一个有10张反对票的问题是如何为人们节省更多的时间的?你只需要几张赞成票就可以向任何阅读问题的人表明这个答案应该被考虑。
- 我确实看过你的评论(正如我建议人们应该的那样:—)。我只是不同意。在我看来,赞成票的数目可以表明答案的优越性,但更可能是问题的频率。我自己已经在Java中编程很多年了,但是我不跟踪所有语言的最新添加,并希望快速检查是否有更好的方法来完成这个通常需要的功能。如果我收回我的赞成票,你会感觉好点吗?
- 此方法不能与基元一起使用!我只是在尝试用一个整数数组做类似的事情之后才发现这个问题。
- @愚人的耶稣"赞成票的数目可以显示出优秀的答案,但也许更频繁的问题。"同意!实际上,我认为这些分数甚至可以转化为谷歌搜索排名。因此,对常见问题的良好回答将在排名中处于较高水平。听起来不错!
- 很抱歉,只有在数组很小的特定示例中,这才是一个很好的答案。但是作为一个通用的解决方案?将数组转换为集合,这样您就可以使用该集合来仔细阅读它本身,并告诉您其中是否存在某些内容?可怕的。
- @TGM1024:正如上面您的评论中的其他人所解释的,这只是一个不做任何复制的瘦包装器。stackoverflow.com/questions/1128723/…
- @彼得卡兹,这不是复制。"瘦包装器"不是瘦包装器——它是对每个访问的方法调用。对于真正大的数组,最好不要使用它,让编译器提供访问代码。事实上,如果"通用"定义的一部分包括已经以数组形式存在的大型数据集的可能性,那么它不是一个伟大的通用解决方案。
- @TGM1024:我认为JVM在优化那些返回A[i]或其他东西的简单方法调用方面相当不错。与大多数编译器优化相比,它应该很容易,而且非常有效,因为它有很多优点。
- @PeterOrders,好吧,我将把它留在这里,因为无论集合发生什么优化,您都可能超过数组的优化,除非编译器可以根据集合提示管理(ptr++)样式的优化。但要小心微观基准。他们很难用Java做正确的事情。无论如何,这不是复制数据。
- 用字符串代替int怎么样?
- 对于原语,我们可以这样做:公共整数keycodes[]=keyEvent.keycode_0_
- 它在Android上使用java8生成了java.lang.NoClassDefFoundError: IntStream。
- 注意使用字符串数组时,应将它们与String.equals方法进行比较,而不是与==方法进行比较!
- 只是好奇:contains如何检查数组是否包含它?它是使用equals还是==?
先清除代码。我们已经(更正):
1
| public static final String[] VALUES = new String[] {"AB", "BC", "CD", "AE"}; |
这是一个可变的静态,findbugs会告诉你是非常淘气。它应该是私有的:
1
| private static final String[] VALUES = new String[] {"AB", "BC", "CD", "AE"}; |
(注意,您实际上可以删除new String[];位。)
所以,引用数组是坏的,特别是在这里我们需要一个集合:
1 2 3
| private static final Set <String > VALUES = new HashSet <String >(Arrays. asList(
new String[] {"AB", "BC", "CD", "AE"}
)); |
(像我这样偏执的人,如果把它包在Collections.unmodifiableSet里,可能会感到更自在,甚至可以公开。)
"对于给定的字符串s,是否有一种测试值是否包含s的好方法?"
O(1)。
更新:自Java SE 9以来,我们拥有EDCOX1×8。
1 2 3
| private static final Set <String > VALUES = Set. of(
"AB", "BC", "CD", "AE"
); |
正确的类型,不可变,O(1)和简洁。美丽的。
(更详细地说,CollectionsAPI仍然缺少不变的集合类型,而且语法对我来说仍然太冗长了。)
- 除了首先创建集合是O(N)之外:)
- 如果是静态的,它可能会被使用很多次。因此,与大量线性搜索的成本相比,初始化集合所花费的时间很有可能是非常小的。
- 创建之后,集合将由代码加载时间(技术上是O(N),但实际上是常量)控制。
- @汤霍丁,你为什么说"特别是这里我们要一套"?在这种情况下,集(hashset)的优势是什么?为什么"引用数组"是坏的(用"引用数组"的意思是调用Arrays.asList生成的由数组支持的数组列表)?
- @巴兹布鲁克试图解决的问题是确定一个值是否在一组值内。Set非常适合。"引用数组"是指引用类型的Java语言数组。基元数组虽然不是很好,但在没有必要的笨重的库的情况下,有点缺乏有效的替代方案。Java的后期版本可以支持不可变的无私/值类型,这将改变事物。
- 这个查找不是真的o(log(n))吗?
- @核磁共振a-TreeSet为O(log n)。HashSets按比例缩放,使得桶中元素的平均数大致恒定。至少对于2^30以下的数组。例如,Big-O分析忽略的硬件缓存可能会产生影响。同时假设散列函数有效工作。
- 必须迭代数组才能创建集合。O(n)。然后你可以争辩说,摊余或类似的情况下,这是均匀的,但你必须在某个地方有一个O(N)步骤。
- 这个答案完全正确。大多数注释者都忽略了一点,即如果您首先将对象放置到集合中,那么创建数组的时间不会比创建数组的时间长太多。只需避免使用数组,除非您绝对确定没有其他功能(出于性能目的),否则使用数组是因为您认为在不进行测试的情况下,使用数组的速度会更快,以查看收集实际上是否太慢,首先,这是一个过早优化的完美例子。
你可以使用ApacheCommonsLang的ArrayUtils.contains。
public static boolean contains(Object[] array, Object objectToFind)
注意,如果传递的数组是null,则此方法返回false。
还有一些方法可用于各种基元数组。
例子:
1 2 3 4 5
| String[] fieldsToInclude = {"id", "name", "location" };
if ( ArrayUtils. contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
} |
- 用于78kb Android应用程序的300kb库,并不总是好的
- 我同意,但这比"滚动自己"更好,更容易阅读原始的Java方式。
- 包:org.apache.commons.lang.arrayutils
- @MAX4EVER有时您已经包含了这个库(出于其他原因),它是一个完全有效的答案。我在找这个,我已经依赖ApacheCommonsLang了。谢谢你的回答。
- 或者你可以复制这个方法(如果有的话,还可以复制Depedencies)。
- 如果您的项目中已经有了ApacheCommonsLang,那么这是最好的方法。如果你没有。你必须写你的一个方法。
- @MAX4任何时候,大多数Android应用程序都被Proguard最小化,只将你需要的类和功能放入你的应用程序中。这使得它等于滚动您自己的,或者复制Apache的源代码。而那些不使用这种最小化的人就不需要抱怨700kb或78kb:。
- 有时我们用激光击落蚊子。没什么问题;)
- 谢谢。与其他解决方案相比,此解决方案的一个优点是,它对任何人都应该是完全可读的,例如,如果value在some range of valuesdo a中,如果some other range of valuesdo b中,等等。重要的是,如果您知道您的代码可能会由其他人维护,使他们的生活更容易比最终的jar大小更重要,或者速度。
只需手动执行即可:
1 2 3 4 5 6 7
| public static <T> boolean contains(final T[] array, final T v) {
for (final T e : array)
if (e == v || v != null && v.equals(e))
return true;
return false;
} |
改进:
方法内部的v != null条件是常量。在方法调用期间,它始终计算为相同的布尔值。因此,如果输入array很大,那么只评估一次这个条件就更有效了,我们可以根据结果在for循环中使用一个简化/更快的条件。改进的contains()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static <T> boolean contains2(final T[] array, final T v) {
if (v == null) {
for (final T e : array)
if (e == null)
return true;
}
else {
for (final T e : array)
if (e == v || v.equals(e))
return true;
}
return false;
} |
- 这个解决方案和公认的答案之间的性能差异是什么?
- @这个解决方案显然更快,因为接受的答案将数组包装成一个列表,并调用该列表上的contains()方法,而我的解决方案基本上只做contains()所能做的。
- E=V V V!=null&v.equals(e)---OR语句的第一部分比较e和v。第二部分进行相同的操作(在检查v不为null之后)。为什么你会有这样的实现而不是仅仅(e==v)。你能给我解释一下吗?
- @alastormoody e==v执行引用相等检查,这非常快。如果数组中有相同的对象(通过引用相同),则查找速度会更快。如果它不是同一个实例,它可能仍然与equals()方法声明的相同,如果引用不相同,则检查此项。
- 为什么这个函数不是Java的一部分呢?难怪人们说Java是臃肿的…看看上面所有的答案,当你只需要一个for循环时,使用一组库。现在的孩子们!
- @ PHRACHHAD它是Java的一部分,参见EDCOX1 3
- @如果你看看Arrays和ArrayList的来源,你会发现这并不一定比使用Arrays.asList(...).contains(...)的版本快。创建一个ArrayList的开销非常小,而ArrayList.contains()使用一个比上面显示的更智能的循环(实际上它使用两个不同的循环)(jdk 7)。
- @阿克塞尔,你说得对。对于小型阵列,这绝对是更快的。对于大型数组,这将稍微慢一点,但如果使用基于搜索值为空或不为空的2个循环,这将再次变得稍微快一点。我以前考虑过这两个循环,但为了简单起见省略了它。
- 另见:马铃薯编程。
- -1:如果您需要性能,那么正确的做法是封装数组并缓存您在分配时需要的检查,而不是每次需要进行检查时都对其进行迭代(坦率地说,可能不在JVM中运行)。如果您不这样做,这将更加冗长,而且不具有任何价值。
- @德沃德,我有点不同意。如果需要有关包含操作的性能,则根本不要使用数组(而是使用哈希集)。问题是关于数组,所以我演示了如何使用数组。第一个解决方案只是一个简单的循环,一点也不复杂。另外,如果已经给出了一个数组,并且您几乎没有选择或者没有选择数据结构,那么改进的版本确实有价值。
- 但问题在于,从概念上讲,您不想教人们获取一个潜在的大型数据结构(数组),然后将其转换为另一个大型结构(集合),这样您就可以让第二个结构仔细阅读自己。最重要的原因是1。令人遗憾的是,这是不必要的。该集合搜索机制的实际实现必须被视为不透明的,因为它可以在将来的Java修订中改变。这只是原则上的卑鄙想法。
- en.wikipedia.org/wiki/loop-invariant_code_motion"改进"是无用的,任何合理的编译器(包括热点中的c1和c2)都会将空检查移出循环,因为参数是最终的,不能更改。
- 此外,您可以使用objets.equals来完全避免检查。调用将被内联,从而产生相同的机器代码和相同的性能。
- 如果您不想在"array"为空时抛出一个NPE,那么相应的部分应该被一个空检查所包围->if(array!= NULL)。
如果数组未排序,则必须遍历所有内容,并对每个内容调用equals。
如果对数组进行排序,则可以执行二进制搜索,数组类中有一个。
一般来说,如果您要进行大量的成员资格检查,您可能希望将所有内容存储在一个集合中,而不是数组中。
- 另外,正如我在回答中所说,如果使用array类,可以对数组进行排序,然后对新排序的数组执行二进制搜索。
- @托马斯:我同意。或者你可以把所有的东西都添加到树集中;同样的复杂性。如果数组不变的话,我会使用它(可能会节省一些内存位置,因为引用是连续的,而字符串不是连续的)。如果这会随着时间的推移而改变的话,我会使用这个套装。
检查数组是否包含值的四种不同方法
1)使用列表:
1 2 3
| public static boolean useList (String[] arr, String targetValue ) {
return Arrays. asList(arr ). contains(targetValue );
} |
2)使用集合:
1 2 3 4
| public static boolean useSet (String[] arr, String targetValue ) {
Set <String > set = new HashSet <String >(Arrays. asList(arr ));
return set. contains(targetValue );
} |
3)使用简单的循环:
1 2 3 4 5 6 7
| public static boolean useLoop (String[] arr, String targetValue ) {
for (String s : arr ) {
if (s. equals(targetValue ))
return true;
}
return false;
} |
4)使用array.binarysearch():
下面的代码是错误的,为了完整起见,这里列出了它。BinarySearch()只能用于已排序的数组。你会发现下面的结果很奇怪。这是对数组排序时的最佳选项。
1 2 3 4
| public static boolean binarySearch (String[] arr, String targetValue ) {
int a = Arrays. binarySearch(arr, targetValue );
return a > 0;
} |
快速实例:
1 2 3 4 5
| String testValue ="test";
String newValueNotInList ="newValue";
String[] valueArray = {"this", "is", "java" , "test" };
Arrays. asList(valueArray ). contains(testValue ); // returns true
Arrays. asList(valueArray ). contains(newValueNotInList ); // returns false |
- 二进制搜索示例应返回大于0的值;
- 为什么?我认为它应该返回一个>-1,因为0表示它包含在数组的头部。
- 带有(a >= 0)的第一个变量是正确的,只需检查文档,它们就会说"注意,这保证了如果并且仅在找到键的情况下返回值将大于等于0"。
值得一提的是,我做了一个测试,比较了3种速度建议。我生成随机整数,将其转换为字符串并将其添加到数组中。然后,我搜索尽可能多的数字/字符串,这对于asList().contains()来说是最坏的情况。
使用10 k数组大小时,结果是:
1 2 3
| Sort & Search : 15
Binary Search : 0
asList.contains : 0 |
使用100K数组时,结果是:
1 2 3
| Sort & Search : 156
Binary Search : 0
asList.contains : 32 |
因此,如果数组是按排序顺序创建的,那么二进制搜索是最快的,否则asList().contains将是最快的方法。如果您有许多搜索,那么对数组进行排序以便使用二进制搜索可能是值得的。这完全取决于您的应用程序。
我想这是大多数人所期望的结果。测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import java.util.*;
public class Test
{
public static void main (String args [])
{
long start = 0;
int size = 100000;
String[] strings = new String[size ];
Random random = new Random();
for (int i = 0; i < size ; i ++)
strings [i ] ="" + random. nextInt( size );
start = System. currentTimeMillis();
Arrays. sort(strings );
System. out. println(Arrays. binarySearch(strings, "" + (size - 1) ));
System. out. println("Sort & Search :" + (System. currentTimeMillis() - start ));
start = System. currentTimeMillis();
System. out. println(Arrays. binarySearch(strings, "" + (size - 1) ));
System. out. println("Search :" + (System. currentTimeMillis() - start ));
start = System. currentTimeMillis();
System. out. println(Arrays. asList(strings ). contains("" + (size - 1) ));
System. out. println("Contains :" + (System. currentTimeMillis() - start ));
}
} |
- 我不明白这个密码。对数组"字符串"进行排序,并在对BinarySearch的两个调用中使用相同的(已排序的)数组。如何显示热点运行时优化之外的任何内容?与aslist.contains调用相同。从排序的数组中创建一个列表,然后用最大的值包含它。当然要花时间。这个测试的意义是什么?更不用说是一个写得不正确的微基准
- 此外,由于二进制搜索只能应用于排序集,所以排序和搜索是使用二进制搜索的唯一可能方法。
- 排序可能是由于许多其他原因而完成的,例如,它可以在init上排序,并且永远不会更改。在测试自己的搜索时间时有用处。然而,这一下降的原因在于,它并不是一个典型的微生物标记的例子。众所周知,微基准在Java中是很难得到的,例如,在运行实际测试之前,必须执行足够的测试代码来获得热点优化,更不用说用计时器运行一次以上的实际测试代码。示例陷阱
- 此测试有缺陷,因为它在同一个JVM实例中运行所有3个测试。后期的测试可以从早期的缓存、JIT等预热中获益。
- 这个测试实际上完全无关。排序和搜索是线性(n*log(n))复杂性,二进制搜索是对数的,数组是线性的。由于这些解决方案在完全不同的复杂性类中,因此没有必要对它们进行比较。
使用Java 8可以创建流并检查流中的任何条目是否匹配EDCOX1 OR 12:
1 2
| String[] values = {"AB", "BC", "CD", "AE"};
boolean sInArray = Arrays. stream(values ). anyMatch("s"::equals ); |
或作为通用方法:
1 2 3
| public static <T > boolean arrayContains (T [] array, T value ) {
return Arrays. stream(array ). anyMatch(value ::equals );
} |
- 同样值得注意的是原始的专门化。
- 另外,anyMatchjavadoc声明它是"...May not evaluate the predicate on all elements if not necessary for determining the result.",因此在找到匹配项后可能不需要继续处理。
您可以使用array.as list方法直接将其初始化为列表,而不是使用快速数组初始化语法,例如:
1
| public static final List <String > STRINGS = Arrays. asList("firstString", "secondString" ...., "lastString"); |
然后你可以这样做(如上所述):
1
| STRINGS.contains("the string you want to find"); |
可以使用Arrays类对值执行二进制搜索。如果数组未排序,则必须使用同一类中的排序函数对数组进行排序,然后对其进行搜索。
- 您可以在同一个类中使用排序函数来完成这一点……我应该将其添加到我的答案中。
- 可能比aslist()花费更多。那么,我认为contains()方法。除非您需要经常进行检查(但如果它只是一个静态的值列表,可以从中开始排序,那就公平了)。
- 真的。关于哪一个最有效,有很多变数。不过,还是有选择的好。
- 你能告诉我们怎么做吗?
- 这里的一些代码是:stackoverflow.com/a/48242328/9131078
- 为了搜索而对整个数组进行排序是很昂贵的。我们可以使用相同的CPU时间进行线性搜索本身。我更喜欢对已经预先按排序顺序构造的集合进行二进制搜索。
顽固分子(但我认为在这里有个教训):
1 2 3 4 5 6 7 8 9 10
| enum Values {
AB, BC, CD, AE
}
try {
Values. valueOf(s );
return true;
} catch (IllegalArgumentException exc ) {
return false;
} |
- 异常抛出显然很重,但如果它有效的话,这将是一种新的测试值的方法。缺点是枚举必须事先定义。
实际上,如果按照Tom Hawtin的建议使用hashset,则无需担心排序问题,而且您的速度与预排序数组上的二进制搜索速度相同,甚至可能更快。
显然,这完全取决于代码的设置方式,但从我的立场来看,顺序是:
在未排序的数组上:
哈希表
阿斯利特
排序和二进制
在已排序的数组上:
哈希表
二元的
阿斯利特
所以不管怎样,都是为了胜利。
- 哈希集成员应为O(1),排序集合上的二进制搜索应为O(log n)。
如果你有google收藏库,Tom的答案可以通过使用不可变集(http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/immutableset.html)简化很多。
这确实从提议的初始化中消除了很多混乱。
1
| private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE"); |
一种可能的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import java.util.Arrays;
import java.util.List;
public class ArrayContainsElement {
public static final List <String > VALUES = Arrays. asList("AB", "BC", "CD", "AE");
public static void main (String args []) {
if (VALUES. contains("AB")) {
System. out. println("Contains");
} else {
System. out. println("Not contains");
}
}
} |
开发人员经常这样做:
1 2
| Set <String > set = new HashSet <String >(Arrays. asList(arr ));
return set. contains(targetValue ); |
上面的代码可以工作,但不需要先将列表转换为set。将列表转换为集合需要额外的时间。它可以简单到:
1
| Arrays. asList(arr ). contains(targetValue ); |
或
1 2 3 4 5 6
| for(String s : arr ){
if(s. equals(targetValue ))
return true;
}
return false; |
第一个比第二个更可读。
在Java 8中使用流。
1 2 3 4 5 6 7 8 9
| List <String > myList =
Arrays. asList("a1", "a2", "b1", "c2", "c1");
myList
. stream()
. filter(s -> s. startsWith("c"))
. map(String::toUpperCase )
. sorted()
. forEach(System. out::println ); |
使用简单的循环是最有效的方法。
1 2 3 4 5 6 7
| boolean useLoop (String[] arr, String targetValue ) {
for(String s : arr ){
if(s. equals(targetValue ))
return true;
}
return false;
} |
向ProgramCreek致意
- 如果数组在目标值之前包含空引用,则会引发空指针异常。
- if语句应为:if(targetValue.equals(s)),因为string equals具有instanceof checker。
对于有限长度的阵列,请使用以下内容(如Camickr提供的)。重复检查的速度很慢,特别是对于较长的数组(线性搜索)。
1
| Arrays. asList(... ). contains(... ) |
如果您重复检查一组较大的元素,则可以获得快速性能
数组的结构不正确。使用TreeSet并将每个元素添加到其中。它对元素进行排序,并具有快速的exist()方法(二进制搜索)。
如果元素实现了Comparable和,您希望TreeSet相应排序:
ElementClass.compareTo()方法必须与ElementClass.equals()兼容:看三合会没有出现打架?(Java设置缺少一个项)
1 2 3 4 5 6 7
| TreeSet myElements = new TreeSet();
// Do this for each element (implementing *Comparable*)
myElements. add(nextElement );
// *Alternatively*, if an array is forceably provided from other code:
myElements. addAll(Arrays. asList(myArray )); |
否则,请使用您自己的Comparator:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class MyComparator implements Comparator <ElementClass > {
int compareTo (ElementClass element1 ; ElementClass element2 ) {
// Your comparison of elements
// Should be consistent with object equality
}
boolean equals (Object otherComparator ) {
// Your equality of comparators
}
}
// construct TreeSet with the comparator
TreeSet myElements = new TreeSet(new MyComparator ());
// Do this for each element (implementing *Comparable*)
myElements. add(nextElement ); |
回报:检查某些元素的存在:
1 2
| // Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement); |
- 为什么要麻烦TreeSet?HashSet更快(o(1)),不需要订购。
试试这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ArrayList <Integer > arrlist = new ArrayList <Integer >(8);
// use add() method to add elements in the list
arrlist. add(20);
arrlist. add(25);
arrlist. add(10);
arrlist. add(15);
boolean retval = arrlist. contains(10);
if (retval == true) {
System. out. println("10 is contained in the list");
}
else {
System. out. println("10 is not contained in the list");
} |
使用以下方法(本代码中的contains()方法为ArrayUtils.in()):
对象实用程序.java
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class ObjectUtils {
/**
* A null safe method to detect if two objects are equal.
* @param object1
* @param object2
* @return true if either both objects are null, or equal, else returns false.
*/
public static boolean equals (Object object1, Object object2 ){
return object1 ==null ? object2 ==null : object1. equals(object2 );
}
} |
Java语言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class ArrayUtils{
/**
* Find the index of of an object is in given array, starting from given inclusive index.
* @param ts Array to be searched in.
* @param t Object to be searched.
* @param start The index from where the search must start.
* @return Index of the given object in the array if it is there, else -1.
*/
public static <T> int indexOf(final T[] ts, final T t, int start){
for(int i = start; i < ts.length; ++i)
if(ObjectUtils.equals(ts[i], t))
return i;
return -1;
}
/**
* Find the index of of an object is in given array, starting from 0;
* @param ts Array to be searched in.
* @param t Object to be searched.
* @return indexOf(ts, t, 0)
*/
public static <T> int indexOf(final T[] ts, final T t){
return indexOf(ts, t, 0);
}
/**
* Detect if the given object is in the given array.
* @param ts Array to be searched in.
* @param t Object to be searched.
* @return If indexOf(ts, t) is greater than -1.
*/
public static <T> boolean in(final T[] ts, final T t){
return indexOf(ts, t) > -1 ;
}
} |
正如您在上面的代码中看到的,在其他地方也使用了其他实用方法ObjectUtils.equals()和ArrayUtils.indexOf()。
- 我很晚才参加这个讨论,但由于我在解决这个问题上的方法,几年前当我面对它时,与这里已经发布的其他答案有点不同,我将在这里发布我当时使用的解决方案,以防有人发现它有用。
如果你不想让它区分大小写
1
| Arrays. stream(VALUES ). anyMatch(s ::equalsIgnoreCase ); |
检查这个
1 2 3 4 5 6 7 8 9 10 11 12 13
| String[] VALUES = new String[] {"AB", "BC", "CD", "AE"};
String s ;
for(int i =0; i < VALUES. length ; i ++)
{
if ( VALUES [i ]. equals(s ) )
{
// do your stuff
}
else{
//do your stuff
}
} |
- 这仍然有效,尽管效率较低
- 这不起作用-它将为每一个不匹配的项输入else(因此,如果您在该数组中查找"ab",它将转到那里3次,因为其中3个值不是"ab")。
arrays.aslist()->然后调用contains()方法将始终有效,但是搜索算法要好得多,因为您不需要在数组周围创建轻量级的列表包装器,这就是arrays.aslist()所做的。
1 2 3 4 5 6 7 8
| public boolean findString (String[] strings, String desired ){
for (String str : strings ){
if (desired. equals(str )) {
return true;
}
}
return false; //if we get here… there is no desired String, return false.
} |
- Arrays.asList不是o(n)。它只是一个轻量级的包装。看看这个实现。
是否使用Array.BinarySearch(array,obj)在数组中查找给定对象。
例子:
1
| if (Array. BinarySearch(str, i ) > -1)` → true --exists |
假--不存在
- 请注意,需要对数组进行排序才能使其正常工作。
- EDCOX1、2和EDCOX1、3是.NET方法,Java中不存在。
- AtayLor有Ajay.BiaLaScript在Java中。但你是对的,没有数组.findindex
创建一个最初设置为假的布尔值。运行一个循环来检查数组中的每个值,并与要检查的值进行比较。如果有匹配,请将Boolean设置为true并停止循环。然后断言布尔值为真。