Java 字符串。包含VS集合<;字符串>。包含VS Regex String.matches()
我在两个文件中有两组不太长的字符串(200~500个单词),如下所示:Java 字符串。包含VS集合<;字符串>。包含VS Regex String.matches(),java,string,set,Java,String,Set,我在两个文件中有两组不太长的字符串(200~500个单词),如下所示: File1 File2 this window that good word work java fine book home 所有独特的词语 现在,首先从文件中读取字符串(逐行),并将其存储在: Set-set1 Set-set2:看起来可能是这样的:[这个,那个,单词,java,书]和[窗口,好,工作
File1 File2
this window
that good
word work
java fine
book home
所有独特的词语
现在,首先从文件中读取字符串(逐行),并将其存储在:
Set-set1 Set-set2
:看起来可能是这样的:[这个,那个,单词,java,书]
和[窗口,好,工作,好,家]
String-str1-String-str2
:可能是这样的:str1:thisthatwordjava
和str2:windowgoodworkfinehome
或可以是str1:this,That,word,java
(用逗号分隔)home
,其中Set
或String
将出现:
set1/2.contains(“主页”)
- 你的字符串列表很短
- 要比较的字符串很短
- 您希望执行一次性查找
Set
方法将更好地扩展和工作。当然,与单个字符串相比,集合会有内存开销,但即使要存储数百万个字符串并比较长字符串,O(1)查找也会保持不变
为正确的作业提供正确的数据结构和算法
使用更安全和更稳健的设计,尤其是在这里,它不是一个难以实现的解决方案。正如你提到的,你会经常检查,那么一套方法对你来说肯定更好
此外,String.contain将是不安全的,因为如果两者都有匹配的字符串和子字符串,则查找将失败。正如kennytm在评论中所说,如果我们使用您的示例,并且您的列表中有“java”字符串,那么查找“ava”将匹配它,这显然是您不想要的
选择正确的一组
不过,您可能不想使用简单哈希集或调整其设置。例如,如果您的集合只创建一次,但经常检查,则可以考虑一个番石榴iMunababele.
例子
假设您想要一个不可变的集合(正如您所说的从文件中读取字符串列表),我会这样做。这是即时的,没有验证,所以请原谅缺乏仪式
使用Java8+Guava
import com.google.common.collect.ImmutableSet;
导入com.google.common.io.Files;
导入com.google.common.base.Splitter;
最终设置lookupTable=ImmutableSet.copyOf(
Splitter.on(',')
.trimpresults()
.省略空字符串()
.split(Files.asCharSource(新文件(“您的文件路径”)、Charsets.UTF_8.read())
);
用正确的路径、正确的字符集、有无修剪来调味,如果你想留出空格和空字符串
仅使用Java8
如果您不想使用番石榴,而只想使用香草Java,那么只需在Java8中执行类似的操作(再次道歉,未经测试):
final Set lookupTable=
Files.line(PATH.get(“您的文件路径”))
.map(直线->直线分割(“,+”)
.map(数组::流)
.收集(toSet());
使用Java<8
如果Java<8,则使用常用的FileInputStream读取文件,然后使用String.split[]或StringTokenizer提取数组,最后将数组项添加到集合中 我猜您还是将文件的行读入字符串,因此如果只计划一次查询,则将其拆分并将子字符串存储在一个集合中并不是最佳选择。如果您想了解性能差异的相关信息。简单地测量一下。这是给你的测试设置
final int WORDS = 10000;
final int SEARCHES = 1000000;
Set<String> strSet = new TreeSet<String>();
String strStr = "";
int[] searches = new int[SEARCHES];
Random randomGenerator = new Random();
// filling set and string
for(int i = 0; i < WORDS; i++){
strSet.add(String.valueOf(i));
strStr += "," + String.valueOf(i);
}
// creating searches
for(int i = 0; i < SEARCHES; i++)
searches[i] = randomGenerator.nextInt(WORDS);
// measure set
long startTime = System.currentTimeMillis();
for(int i = 0; i < SEARCHES; i++)
strSet.contains(String.valueOf(searches[i]));
System.out.println("set result " + (System.currentTimeMillis() - startTime));
// measure string
startTime = System.currentTimeMillis();
for(int i = 0; i < SEARCHES; i++)
strStr.contains(String.valueOf(searches[i]));
System.out.println("string result " + (System.currentTimeMillis() - startTime));
final int WORDS=10000;
最终整数搜索=1000000;
Set strSet=new TreeSet();
字符串strStr=“”;
int[]searches=新int[searches];
Random randomGenerator=新的Random();
//填充装置和字符串
for(int i=0;i
对我来说,输出是一个有意义的证据,证明您应该使用集合
设置结果350字符串结果14197
如果给定的单词没有comas,Set应该占用更多的内存空间,但执行时间更少(可以通过简单的拆分完成)
但我真正认为最好的方法是实验证明系统。currentTimeMillis()
String.contains()
将为“ava”
返回true。我的预感是设置会更好。因为我猜它是用对象的散列来比较相等的。@kennytm如果在检查之前在输入字符串的开头和结尾加上逗号,它就不会这样做了。在字符串的集合中存储单个字符串的原因是什么?请阅读并提供不清楚你在问什么
@BahramdunAdil你是否分析了你的程序并发现集合比较是一个热点?如果他只需要做一次查找,一个字符串。包含
w
final Set<String> lookupTable =
Files.lines(Paths.get("YOUR_FILE_PATH"))
.map(line -> line.split(",+"))
.map(Arrays::stream)
.collect(toSet());
final int WORDS = 10000;
final int SEARCHES = 1000000;
Set<String> strSet = new TreeSet<String>();
String strStr = "";
int[] searches = new int[SEARCHES];
Random randomGenerator = new Random();
// filling set and string
for(int i = 0; i < WORDS; i++){
strSet.add(String.valueOf(i));
strStr += "," + String.valueOf(i);
}
// creating searches
for(int i = 0; i < SEARCHES; i++)
searches[i] = randomGenerator.nextInt(WORDS);
// measure set
long startTime = System.currentTimeMillis();
for(int i = 0; i < SEARCHES; i++)
strSet.contains(String.valueOf(searches[i]));
System.out.println("set result " + (System.currentTimeMillis() - startTime));
// measure string
startTime = System.currentTimeMillis();
for(int i = 0; i < SEARCHES; i++)
strStr.contains(String.valueOf(searches[i]));
System.out.println("string result " + (System.currentTimeMillis() - startTime));