我有一个包含以下内容的CSV文件:
2017-10-29 00:00:00.0,"1005",-10227,0,0,0,332894,0,0,222,332894,222,332894
2017-10-29 00:00:00.0,"1010",-125529,0,0,0,420743,0,0,256,420743,256,420743
2017-10-29 00:00:00.0,"1005",-10227,0,0,0,332894,0,0,222,332894,222,332894
2017-10-29 00:00:00.0,"1013",-10625,0,0,-687,599098,0,0,379,599098,379,599098
2017-10-29 00:00:00.0,"1604",-1794.9,0,0,-3.99,4081.07,0,0,361,4081.07,361,4081.07
因此第1行和第3行是重复的。 现在我想读入文件并在控制台中打印出重复的行。
我设置了这个Java代码,读取文件并将其逐行放入ArrayList中。然后我创建一个不可变的 复制,循环遍历ArrayList,在binarySearch中我使用ArrayList的不可变副本:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ReadValidationFile {
public static void main(String[] args) {
List<String> validationFile = new ArrayList<>();
try(BufferedReader br = new BufferedReader(new FileReader("validation_small.csv"));){
String line;
while((line = br.readLine())!= null){
validationFile.add(line);
}
} catch (FileNotFoundException e) {
//e.printStackTrace();
System.out.println("file not found " + e.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
List<String> validationFileCopy = Collections.unmodifiableList(validationFile);
for(String line : validationFile){
int comp = Collections.binarySearch(validationFileCopy,line,new ComparatorLine());
if (comp <= 0){
System.out.println(line);
}
}
}
}
比较类:
import java.util.Comparator;
public class ComparatorLine implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
return s1.compareToIgnoreCase(s2);
}
}
我希望打印这一行:
2017-10-29 00:00:00.0,"1005",-10227,0,0,0,332894,0,0,222,332894,222,332894
但我得到的输出是:
2017-10-29 00:00:00.0,"1010",-125529,0,0,0,420743,0,0,256,420743,256,420743
你能帮我看看我做错了什么吗?我认为我的比较器没问题。我有什么问题 的ArrayLists?
谢谢你, 彼得
答案 0 :(得分:3)
在从输入csv文件中读取行时创建Set
,随时设置add()
元素返回false打印该行,因为它是重复行。
如果您需要所有重复行的列表,请创建一个List
,其中包含在审核false
至add()
时返回Set
的行。
注意:
Set
将数据插入add(line.toLowerCase())
,这将确保将所有行与小写进行比较,然后添加到{ {1}}。Set
答案 1 :(得分:3)
其他答案正确地说明您应该使用Set而不是List。但是为了学习,让我们看看你的代码,看看你哪里出错了。
public class ReadValidationFile {
public static void main(String[] args) {
List<String> validationFile = new ArrayList<>();
try(BufferedReader br = new BufferedReader(new FileReader("validation_small.csv"));){
分号是不必要的。
String line;
while((line = br.readLine())!= null){
validationFile.add(line);
}
这一切都可以在一行中实现:
List<String> validationFile = Files.readAllLines(Paths.get("validation_small.csv"), "utf-8");
} catch (FileNotFoundException e) {
//e.printStackTrace();
System.out.println("file not found " + e.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
List<String> validationFileCopy = Collections.unmodifiableList(validationFile);
实际上,这不是副本。这只是同一列表的不可修改的视图。
for(String line : validationFile){
int comp = Collections.binarySearch(validationFileCopy,line,new ComparatorLine());
您也可以只搜索validationFile
本身。但是,您调用的binarySearch
仅适用于已排序的列表,但您的列表未排序。请参阅documentation。
if (comp <= 0){
System.out.println(line);
}
如果找不到 (comp <= 0
),则表示正在打印。如果搜索成功,则会返回非负数(comp >= 0
)。但另一个问题是,您正在搜索每个元素的整个列表,搜索显然总是成功(即,如果您的列表已排序)。
省去所有麻烦并使用Set代替。并且,使用Java 8流,整个程序可以简化为以下内容:
public static void main(String[] args) throws Exception {
Set<String> uniqueLines = new HashSet<>();
Files.lines(Paths.get("", "utf-8"))
.filter(line -> !uniqueLines.add(line))
.forEach(System.out::println);
}
如果你真的需要在比较字符串时忽略大小写(从你给定的数据看起来它看起来没有任何区别,因为它只是数字),然后通过第一个大写字母存储每个唯一的行和然后降低它。这种显然繁琐的技术是必要的,因为如果处理非英语文本只是小写是不够的。 equalsIgnoreCase方法也可以这样做。
public static void main(String[] args) throws Exception {
Set<String> uniqueLines = new HashSet<>();
Files.lines(Paths.get("", "utf-8"))
.filter(line -> !uniqueLines.add(line.toUpperCase().toLowerCase()))
.forEach(System.out::println);
}
答案 2 :(得分:1)
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class ReadValidationFile {
public static void main(String[] args){
List<String> validationFile = new ArrayList<>();
try(BufferedReader br = new BufferedReader(new FileReader("validation_small.csv"));){
String line;
while((line = br.readLine())!= null){
validationFile.add(line);
}
} catch (FileNotFoundException e) {
//e.printStackTrace();
System.out.println("file not found " + e.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
Set<String> uniques = new HashSet<>();
List<String> duplicates = validationFile.stream().filter(i->!uniques.add(i)).collect(Collectors.toList());
System.out.println(duplicates);
}
}