vb.net是否有更快的方法从另一个字符串中减去一个字符串列表

时间:2012-07-17 16:01:36

标签: vb.net string list

Public done As New List(Of String)
Public thinkingofdoing As New List(Of String)
Public todo As New List(Of String)

done.AddRange(System.IO.File.ReadAllLines("C:\Users\Work\Desktop\done.txt"))
thinkingofdoing.AddRange(System.IO.File.ReadAllLines("C:\Users\Work\Desktop\thinkingofdoing.txt"))

For i = 0 To thinkingofdoing.Count - 1
    ThreadPool.QueueUserWorkItem(AddressOf caldiff, thinkingofdoing(i))
Next

Public Sub caldiff(ByVal tobedone)
    If done.Contains(tobedone) = False Then
        todo.Add(tobedone)
    End If
End Sub

done.txt thinkingofdoing.txt 有500万到800万行

这需要很长时间:(即使是四核AMD 965超频到4.2 GHZ。

3 个答案:

答案 0 :(得分:2)

首先,上述代码无效。 List(Of T)不是线程安全的,因此从多个线程执行此操作实际上会导致重大问题而不进行同步,因为对AddContains的调用本身并不安全。多线程。

更好的选择是选择更好的集合,例如HashSet(Of T),这会使检查更快。我建议像:

public Done as New HashSet(Of String)
public ThinkingOfDoing as IList(Of String) 
public Todo as New List(Of String)

ThinkingOfDoing = System.IO.File.ReadAllLines("C:\Users\Work\Desktop\thinkingofdoing.txt")
Done.AddRange(System.IO.File.ReadAllLines("C:\Users\Work\Desktop\done.txt"))

ToDo = ThinkingOfDoing.Where(Function(i) Done.Contains(i) = False).ToList()

使用HashSet(Of T)Contains()检查会变得更快(O(1)而不是O(n)),这会导致运行批次< / em>更快,甚至单线程。

如果您不需要存储完成,您可以保留数组,并直接使用Enumerable.Except(在内部使用Set):

ThinkingOfDoing = System.IO.File.ReadAllLines("C:\Users\Work\Desktop\thinkingofdoing.txt")
Dim done = System.IO.File.ReadAllLines("C:\Users\Work\Desktop\done.txt")

Dim Todo = ThinkingOfDoing.Except(done).ToList();

答案 1 :(得分:0)

您可以使用效率更高的Enumerable.Except,因为它实现为HashSet<T>

IEnumerable(Of String) newLines = thinkingofdoing.Except(done)

你也应该使用File.ReadLines而不是File.ReadAllLines,因为前者使用流,而后者一次将全部加载到内存中。

我会首先测试性能而不使用ThreadPool

答案 2 :(得分:0)

这个怎么样......

Public done As ISet(Of String) 
Public toDo As New List(Of String)(); 

done = New HashSet(Of String) _
    (System.IO.File.ReadAllLine("C:\Users\Work\Desktop\done.txt")

Using reader As New StreamReader(New FileStream _
        ("C:\Users\Work\Desktop\thinkingofdoing.txt"), FileMode.Open)
    Do While reader.Peek() >= 0
        Dim line = reader.ReadLine()
        If Not done.Contains(line) Then
            toDo.Add(line)
        EndIf
    Loop
End Using

这会将所有已完成的行加载到具有出色查找性能的HashSet中,然后不是将完整的文件内容加载到内存中,而是逐行解析,只有在尚未完成时才添加到todo中

如果VB.Net有一个收益率回报,我会把它放在一个函数中并在IEnumerable上完成ToList但是嘿嘿。