.contains() 不适用于扫描仪是否有原因?
Is there a reason .contains() would not work with scanner?
我正在研究一个线性搜索问题,该问题获取姓名文件并将其与姓名和号码的电话簿文件进行比较。我现在唯一的任务是查看电话簿文件中有多少个名字。在我的主要方法中的 if 语句之前,一切都按预期工作,但对于我的生活,我无法弄清楚我做错了什么。通过测试,我可以打印出两个文件中的所有行,所以我知道我正在正确读取文件。输出应为 500 / 500,因为所有姓名都在超过一百万行的电话簿文件中。请帮忙
package phonebook;
import java.util.Objects;
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class Main {
final static String NAME_PATH = "C:\Users\{user}\Downloads\find.txt";
final static String PHONEBOOK_PATH = "C:\Users\{user}\Downloads\directory.txt";
private static String[] namesList(File file) {
int count = 0;
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
scanner.nextLine();
count++;
}
String[] names = new String[count];
Scanner sc = new Scanner(file);
for (int i = 0; i < count; i++) {
names[i] = sc.nextLine();
}
return names;
} catch (FileNotFoundException e) {
System.out.printf("File not found: %s", NAME_PATH);
return null;
}
}
private static String timeDifference(long timeStart, long timeEnd) {
long difference = timeEnd - timeStart;
long minutes = (difference / 1000) / 60;
long seconds = (difference / 1000) % 60;
long milliseconds = difference - ((minutes * 60000) + (seconds * 1000));
return "Time taken: " + minutes + " min. " + seconds + " sec. " +
milliseconds + " ms.";
}
public static void main(String[] args) {
File findFile = new File(NAME_PATH);
File directoryFile = new File(PHONEBOOK_PATH);
String[] names = namesList(findFile);
int count = 0;
try (Scanner scanner = new Scanner(directoryFile)) {
System.out.println("Start searching...");
long timeStart = System.currentTimeMillis();
for (int i = 0; i < Objects.requireNonNull(names).length; i++) {
while (scanner.hasNextLine()) {
if (scanner.nextLine().contains(names[i])) {
count++;
break;
}
}
}
long timeEnd = System.currentTimeMillis();
System.out.print("Found " + count + " / " + names.length + " entries. " +
timeDifference(timeStart, timeEnd));
} catch (FileNotFoundException e) {
System.out.printf("File not found: %s", PHONEBOOK_PATH);
}
}
}
输出:
Start searching...
Found 1 / 500 entries. Time taken: 0 min. 0 sec. 653 ms.
Process finished with exit code 0
您正在为每个名称在文件中向前移动(使用 nextLine),您应该改为对每一行的名称进行循环。
在您的代码中,如果您的名字 (name[0]) 位于文件的最后一行,那么您在第一次迭代时已经位于文件末尾,并且在搜索第二个名字时,已经没有更多的行了。
尝试这样的事情:
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
for (int i = 0; i < Objects.requireNonNull(names).length; i++) {
if (line.contains(names[i])) {
count++;
break;
}
}
}
问题在于您的搜索方式。如果您想迭代搜索,则需要为每个名称重新开始迭代。否则,您只是在 phone 书中向前搜索。如果名字列表中的第二个名字出现在第一个名字之前,那么您将只能找到一个名字,因为您将在找到任何东西之前用尽 phone这本书。
但是,反复阅读 phone 图书文件是一项代价高昂的工作。相反,加载 phone 列表(就像您对名称列表所做的那样),然后您可以迭代地在该列表中搜索名称列表中的每个元素。以下示例假设您使用的是 List 而不是数组。使用 for-each 循环使正在发生的事情一目了然(相对于使用 Stream API)。
List<String> names = loadNames();
// each phonebook entry contains the name and the phone number in one string
List<String> phonebook = loadPhonebook();
int numFound = 0;
for (String name : names) {
for (String entry : phonebook) {
if (entry.contains(name)) {
++numFound;
}
}
}
但是,这仍然是一项昂贵的任务,因为您要反复进行嵌套迭代。根据 phonebook 文件的格式,您应该能够解析出名称并将它们存储在 TreeSet 中。那么查找就是常数时间
List<String> names = loadNames();
// phonebookNames are just the names - the phone number has been stripped away
TreeSet<String> phonebookNames = loadPhonebookNames();
int numFound = 0;
for (String name : names) {
if (phonebookNames.contains(name)) {
++numFound;
}
}
据推测,您的作业最终会想要使用 phone 号码来做某事,所以您可能不想把它丢在地上。您可以使用 Map
(key=name, value=phone数字)。那么你就可以这样统计名字的存在了。
List<String> names = loadNames();
// phonebook is a Map of phone number values keyed on name
Map<String,String> phonebook = loadPhonebook();
int numFound = 0;
for (String name : names) {
if (phonebook.containsKey(name)) {
++numFound;
}
}
我正在研究一个线性搜索问题,该问题获取姓名文件并将其与姓名和号码的电话簿文件进行比较。我现在唯一的任务是查看电话簿文件中有多少个名字。在我的主要方法中的 if 语句之前,一切都按预期工作,但对于我的生活,我无法弄清楚我做错了什么。通过测试,我可以打印出两个文件中的所有行,所以我知道我正在正确读取文件。输出应为 500 / 500,因为所有姓名都在超过一百万行的电话簿文件中。请帮忙
package phonebook;
import java.util.Objects;
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class Main {
final static String NAME_PATH = "C:\Users\{user}\Downloads\find.txt";
final static String PHONEBOOK_PATH = "C:\Users\{user}\Downloads\directory.txt";
private static String[] namesList(File file) {
int count = 0;
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
scanner.nextLine();
count++;
}
String[] names = new String[count];
Scanner sc = new Scanner(file);
for (int i = 0; i < count; i++) {
names[i] = sc.nextLine();
}
return names;
} catch (FileNotFoundException e) {
System.out.printf("File not found: %s", NAME_PATH);
return null;
}
}
private static String timeDifference(long timeStart, long timeEnd) {
long difference = timeEnd - timeStart;
long minutes = (difference / 1000) / 60;
long seconds = (difference / 1000) % 60;
long milliseconds = difference - ((minutes * 60000) + (seconds * 1000));
return "Time taken: " + minutes + " min. " + seconds + " sec. " +
milliseconds + " ms.";
}
public static void main(String[] args) {
File findFile = new File(NAME_PATH);
File directoryFile = new File(PHONEBOOK_PATH);
String[] names = namesList(findFile);
int count = 0;
try (Scanner scanner = new Scanner(directoryFile)) {
System.out.println("Start searching...");
long timeStart = System.currentTimeMillis();
for (int i = 0; i < Objects.requireNonNull(names).length; i++) {
while (scanner.hasNextLine()) {
if (scanner.nextLine().contains(names[i])) {
count++;
break;
}
}
}
long timeEnd = System.currentTimeMillis();
System.out.print("Found " + count + " / " + names.length + " entries. " +
timeDifference(timeStart, timeEnd));
} catch (FileNotFoundException e) {
System.out.printf("File not found: %s", PHONEBOOK_PATH);
}
}
}
输出:
Start searching...
Found 1 / 500 entries. Time taken: 0 min. 0 sec. 653 ms.
Process finished with exit code 0
您正在为每个名称在文件中向前移动(使用 nextLine),您应该改为对每一行的名称进行循环。
在您的代码中,如果您的名字 (name[0]) 位于文件的最后一行,那么您在第一次迭代时已经位于文件末尾,并且在搜索第二个名字时,已经没有更多的行了。
尝试这样的事情:
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
for (int i = 0; i < Objects.requireNonNull(names).length; i++) {
if (line.contains(names[i])) {
count++;
break;
}
}
}
问题在于您的搜索方式。如果您想迭代搜索,则需要为每个名称重新开始迭代。否则,您只是在 phone 书中向前搜索。如果名字列表中的第二个名字出现在第一个名字之前,那么您将只能找到一个名字,因为您将在找到任何东西之前用尽 phone这本书。
但是,反复阅读 phone 图书文件是一项代价高昂的工作。相反,加载 phone 列表(就像您对名称列表所做的那样),然后您可以迭代地在该列表中搜索名称列表中的每个元素。以下示例假设您使用的是 List 而不是数组。使用 for-each 循环使正在发生的事情一目了然(相对于使用 Stream API)。
List<String> names = loadNames();
// each phonebook entry contains the name and the phone number in one string
List<String> phonebook = loadPhonebook();
int numFound = 0;
for (String name : names) {
for (String entry : phonebook) {
if (entry.contains(name)) {
++numFound;
}
}
}
但是,这仍然是一项昂贵的任务,因为您要反复进行嵌套迭代。根据 phonebook 文件的格式,您应该能够解析出名称并将它们存储在 TreeSet 中。那么查找就是常数时间
List<String> names = loadNames();
// phonebookNames are just the names - the phone number has been stripped away
TreeSet<String> phonebookNames = loadPhonebookNames();
int numFound = 0;
for (String name : names) {
if (phonebookNames.contains(name)) {
++numFound;
}
}
据推测,您的作业最终会想要使用 phone 号码来做某事,所以您可能不想把它丢在地上。您可以使用 Map
(key=name, value=phone数字)。那么你就可以这样统计名字的存在了。
List<String> names = loadNames();
// phonebook is a Map of phone number values keyed on name
Map<String,String> phonebook = loadPhonebook();
int numFound = 0;
for (String name : names) {
if (phonebook.containsKey(name)) {
++numFound;
}
}