将数据转换为其他列表的速度更快

时间:2015-08-03 13:35:04

标签: c# .net list

我需要将数据从一个列表转换为另一个列表。我需要我的代码看起来完全像那样(只是我必须完成的要求):

public interface IHuman
{
        string name { get; set; }
        string lastName { get ;set; }
        int age { get; set; }
}

我还有其他两个课程:

public class HumanA : IHuman
{
    //Implementation
}

public class HumanB : IHuman
{
    //Implementation
}

在我的计划中,我有这个部分:

List<HumanA> listA = some data

我需要将HumanA列表中的数据写入HumanB列表,它必须是此列表中没有其他组合。

有没有比这更简单的方法:

list<HumanB> listB = listA.ConverAll(x => new HumanA()
{
    name = x.name,
    lastName = x.lastName,
    age = x.age
});

应该是因为HumanA和HumanB只有IHuman的属性实现但是我不能使用:

list<IHuman>

4 个答案:

答案 0 :(得分:2)

如果您想要在运行时方面采用更快方式,您希望避免linq的任何开销,并尽可能地集中精力来限制所需的操作。

这意味着您要避免:

  • 创建迭代器
  • 创建任何lambda函数
  • 调整List - 对象
  • 的存储阵列的大小

因此,您希望使用for - 循环来获取对象,这样您就没有任何迭代器对象,并且您希望创建具有指定容量的新列表,因此不必调整大小。您还想使用构造函数参数设置所需的属性。

除了创建lambda函数(用作转换器)之外,这与ConvertAll - 函数的作用完全相同。所以你不会得到任何比这更快的东西。

如果您想获得一些更简单的代码,建议您实现一个构造函数,该构造函数在两个类中都采用IHuman接口并在那里复制数据。因此,您可以将代码缩减为:

List<HumanB> listB = listA.ConvertAll(x => new HumanB(x));

编辑: 如果我们讨论的是大规模的大型列表和需要相当长时间创建的对象,那么还可以使用多个线程来加快速度。但是对于你提供的简单例子,我非常怀疑这会做什么,只会让事情变得更慢,更复杂。

答案 1 :(得分:2)

Nitram给了你一个非常好的答案,所以我无法提供有关工作代码的更多有用的答案。 BUT

我写了一个小测试,这样你就可以看到自己有什么作用,以及差异是多么微妙。

对测试的一点澄清。

  1. 我使用的列表包含10000个元素。
  2. 每次测试都运行了10次。
  3. 我测试的代码主要由此问题中的答案提供
  4. 这里的代码:

    static void Main(string[] args)
    {
        //Creation
        List<HumanA> listA = new List<HumanA>();
        for (int j = 0; j < 2000; j++)
        {
            listA.Add(new HumanA());
            listA.Add(new HumanA());
            listA.Add(new HumanA());
            listA.Add(new HumanA());
            listA.Add(new HumanA());
        }
    
        Stopwatch stop = new Stopwatch();
        List<HumanB> listB = null;
    
        int roundsToComplete = 10;
    
        long testTime1 = 0;
        long testTime2 = 0;
        long testTime3 = 0;
        long testTime4 = 0;
        long testTime5 = 0;
        long testTime6 = 0;
    
    
        long testTime1ms = 0;
        long testTime2ms = 0;
        long testTime3ms = 0;
        long testTime4ms = 0;
        long testTime5ms = 0;
        long testTime6ms = 0;
    
        for (int rounds = 0; rounds < roundsToComplete; rounds++)
        {
            //Test 1
            stop.Start();
            listB = new List<HumanB>();
            foreach (HumanA humanA in listA)
            {
                HumanB humanB = new HumanB();
                humanB.age = humanA.age;
                humanB.name = humanA.name;
                humanB.lastName = humanA.lastName;
                listB.Add(humanB);
            }
            stop.Stop();
            testTime1 += stop.ElapsedTicks;
            testTime1ms += stop.ElapsedMilliseconds;
            listB.Clear();
            listB = null;
            stop.Reset();
    
            //Test 2
            stop.Start();
            listB = new List<HumanB>();
            foreach (HumanA humanA in listA)
            {
                HumanB humanB = new HumanB(humanA);
                listB.Add(humanB);
            }
            stop.Stop();
            testTime2 += stop.ElapsedTicks;
            testTime2ms += stop.ElapsedMilliseconds;
            listB.Clear();
            listB = null;
            stop.Reset();
    
            //Test 3
            stop.Start();
            listB = listA.ConvertAll(x => new HumanB(x));
            stop.Stop();
            listB.Clear();
            listB = null;
            testTime3 += stop.ElapsedTicks;
            testTime3ms += stop.ElapsedMilliseconds;
    
            //Test 4
            stop.Start();
            int count = listA.Count;
            listB = new List<HumanB>();
            for (int i = 0; i < count; i++)
            {
                listB.Add(new HumanB(listA[i]));
            }
    
            stop.Stop();
            listB.Clear();
            listB = null;
            testTime4 += stop.ElapsedTicks;
            testTime4ms += stop.ElapsedMilliseconds;
    
            //Test 5
            stop.Start();
            listB = listA.Select(x => new HumanB() { name = x.name, lastName = x.lastName, age = x.age }).ToList();
            stop.Stop();
            listB.Clear();
            listB = null;
            testTime5 += stop.ElapsedTicks;
            testTime5ms += stop.ElapsedMilliseconds;
    
    
            //Test6
            stop.Start();
            count = listA.Count;
            listB = new List<HumanB>(count);
            Parallel.For(0, count, c=>
            {
                listB.Add(new HumanB(listA[c])); 
            });
            stop.Stop();
            listB.Clear();
            listB = null;
            testTime6 += stop.ElapsedTicks;
            testTime6ms += stop.ElapsedMilliseconds;
    
    
        }
    
        Console.WriteLine("1: " + testTime1 / roundsToComplete);
        Console.WriteLine("2: " + testTime2 / roundsToComplete);
        Console.WriteLine("3: " + testTime3 / roundsToComplete);
        Console.WriteLine("4: " + testTime4 / roundsToComplete);
        Console.WriteLine("5: " + testTime5 / roundsToComplete);
        Console.WriteLine("6: " + testTime6 / roundsToComplete);
    
        Console.WriteLine("milliseconds 1: " + testTime1ms / roundsToComplete);
        Console.WriteLine("milliseconds 2: " + testTime2ms / roundsToComplete);
        Console.WriteLine("milliseconds 3: " + testTime3ms / roundsToComplete);
        Console.WriteLine("milliseconds 4: " + testTime4ms / roundsToComplete);
        Console.WriteLine("milliseconds 5: " + testTime5ms / roundsToComplete);
        Console.WriteLine("milliseconds 6: " + testTime6ms / roundsToComplete);
    
        Console.ReadLine();
    
    }
    

    以下是以滴答和毫秒为单位的结果

    1: 24944
    2: 4278
    3: 2746
    4: 5003
    5: 9230
    6: 21502
    milliseconds 1: 12
    milliseconds 2: 1
    milliseconds 3: 0
    milliseconds 4: 2
    milliseconds 5: 4
    milliseconds 6: 10
    

答案 2 :(得分:0)

目前还不清楚为什么你必须让你的代码看起来和你一样,就像你说的那样。

在实现界面时,您实际上可以使用下面的代码来获得相同的结果。有效地,HumanA和HumanB是相同的,因为您可以执行以下操作,并将listA和listB定义为IHuman列表,然后将HumanA添加到列表中。

        var listA = new List<IHuman>();

        listA.Add(new HumanA());
        listA.Add(new HumanA());
        listA.Add(new HumanA());

        var listB = new List<IHuman>(listA);

        var humanB = (HumanB)listB[0];

实际上并不需要最后一个CAST行,因为该类实现了与HumanA类相同的所有方法,因为IHuman,除非HumanB有额外的方法,否则需要使用强制转换来访问这些方法。

答案 3 :(得分:-3)

试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<HumanA> aS = new List<HumanA>();

            List<HumanB> bS = aS.Select(x => new HumanB() { name = x.name, lastName = x.lastName, age = x.age }).ToList(); 
        }
    }
    public class IHuman
    {
        public string name { get; set; }
        public string lastName { get ;set; }
        public int age { get; set; }
    }
    public class HumanA : IHuman
    {
    //Implementation
    }
    public class HumanB : IHuman
    {
       //Implementation
    }

}
​