using IteratorPattern;
using System;

namespace MyStructure
{
    class Program
    {
        static void Main(string[] args)
        {
            //1 Array/ArrayList/List/LinkList/Queue/Stack/HashSet/SortedSet
            //  HashTable/SortedList/Dictionary/SortedDictionary

            //2 IEnumerable/ICollection/IList/IQueryble
            //3 迭代器模式、yield
            //4 dynamic关键字

            //a) 集合:纯粹的数据集合,会去重,无序(当然SortedSet有序)
            //b) 线性结构:一对一,数组
            //c) 树形结构:一对多,菜单/文件夹/类别/树形控件/表达式目录树
            //d) 图状结构(网状):多对多,地图/拓扑图/快递

            //dnspy 反编译工具,反编译后可以改代码
            //yield是语法糖,由编译器生成Iterator的代码,Current,MoveNext,Reset

            //动态类型dynamic,framework4.0,弱类型特点;
            //代替反射,不用反射找类的方法,属性了,直接写;数据绑定方便,Json序列化不用再定义类了
            //任何东西和dynamic交互都变成dynamic了

            //CollectionDemo.Show();
            IteratorPattern.IteratorPattern.Show();
        }
    }
}
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;

namespace MyStructure
{
    public class CollectionDemo
    {
        public static void Show()
        {
            //线性结构存储方式分两种:1在内存上连续分配,节约空间,比如数组
            //                        2非连续分配,每个元素存储数据和地址,查询只能顺序查找,读取慢增删快比如链表

            //IEnumerable/ICollection/IList/IQueryble
            //接口是标识功能的,不同的接口拆开,就是为了实现接口隔离,虽然我们的接口内容重复

            //IEnumerable 任何数据集合,都实现这个接口,为了不同的数据结构,提供统一的访问方式,这个就是迭代器模式
            #region Array
            {
                //Array在内存上连续分配,每个元素类型一样
                //可以索引访问,读取快,增删慢,因为被影响的后续元素要位移
                int[] intArray = new int[3];
                intArray[0] = 1233;
                string[] strArray = new string[] { "123", "345" };
            }
            {
                //ArrayList 不定长,连续分配
                //元素没有类型限制,任何元素都被当成object处理,如果是值类型,会有装箱操作
                //现在已经逐渐废弃
                ArrayList arrayList = new ArrayList();
                arrayList.Add("小王");
                arrayList.Add("小高");
                arrayList.Add(18);
                //arrayList[3] = 19;//会报错,只有add会增加数组长度,访问超出索引上限
                var value = arrayList[2];
                arrayList.RemoveAt(2);
                arrayList.RemoveAt(0);
                arrayList.Remove("小高");
            }
            {
                //List  其实也是数组,内存上也是连续摆放,不定长;泛型,保证类型安全,避免装箱拆箱
                List<int> intList = new List<int> { 1, 23, 4, 5 };
                intList.Add(12);
                intList.Add(23);
                intList.Remove(23);//移除第一个
                intList[0] = 11;

                List<string> strList = new List<string> { "1", "2" };
                strList[0] = "123";
            }
            #endregion

            #region 链表
            {
                //LinkedList 泛型,链表,元素不连续分配,  实际应用:令牌环
                //单向链表每个元素都记录下一个节点地址;双向记录上个和下个节点地址
                //不能下表访问,找元素只能遍历
                LinkedList<int> intLinkList = new LinkedList<int>();
                intLinkList.AddFirst(123);
                intLinkList.AddLast(123);

                bool isContain = intLinkList.Contains(123);
                LinkedListNode<int> node = intLinkList.Find(123);//相同值找第一个
                intLinkList.AddBefore(node, 11);
                intLinkList.AddBefore(node, 12);
                intLinkList.AddAfter(node, 22);

                intLinkList.Remove(12);
                intLinkList.Remove(node);
                intLinkList.RemoveFirst();
                intLinkList.RemoveLast();
                intLinkList.Clear();
            }
            {
                //Queue 就是链表,先进先出,任务延迟执行,比如A不断将日志信息放入队列,B不断获取队列的信息输出
                Queue<string> strQueue = new Queue<string>();
                strQueue.Enqueue("one");
                strQueue.Enqueue("two");
                strQueue.Enqueue("three");
                strQueue.Enqueue("four");
                strQueue.Enqueue("five");
                strQueue.Enqueue("six");
                foreach (string str in strQueue)
                {
                    Console.WriteLine(str);
                }

                Console.WriteLine($"Dequeue '{strQueue.Dequeue()}'");//移除第一个元素并返回
                Console.WriteLine($"Peek '{strQueue.Peek()}'");//返回第一个元素
                Console.WriteLine($"Dequeue '{strQueue.Dequeue()}'");

                Queue<string> queueCopy = new Queue<string>(strQueue.ToArray());
                foreach (string str in queueCopy)
                {
                    Console.WriteLine(str);
                }

                Console.WriteLine($"queueCopy.Contains(\"four\"):{queueCopy.Contains("four")}");
                Console.WriteLine($"queueCopy.Count ={queueCopy.Count}");
                queueCopy.Clear();
            }
            {
                Console.WriteLine("****************Stack<T>***************");
                //Stack 就是链表,先进后出,解析表达式目录树的时候,先产生的数据后使用
                //应用:撤销操作命令,最后一个先撤销
                Stack<string> stack = new Stack<string>();
                stack.Push("one");//第一个进去的,位置在最底部
                stack.Push("two");
                stack.Push("three");
                stack.Push("four");
                stack.Push("five");
                stack.Push("six");
                foreach (string str in stack)
                {
                    Console.WriteLine(str);
                }
                Console.WriteLine($"Pop '{stack.Pop()}'");//移除最后一个元素并返回
                Console.WriteLine($"Peek '{stack.Peek()}'");//返回第一个元素
                Console.WriteLine($"Dequeue '{stack.Pop()}'");
                var arr = stack.ToArray();
                Stack<string> stackCopy = new Stack<string>(stack.ToArray());//栈的顺序和数组相反了,因为先进的排在后面
                foreach (string str in stackCopy)
                {
                    Console.WriteLine(str);
                }

                Console.WriteLine($"queueCopy.Contains(\"four\"):{stackCopy.Contains("four")}");
                Console.WriteLine($"queueCopy.Count ={stackCopy.Count}");
                stackCopy.Clear();
            }
            #endregion

            #region 集合Set
            {
                Console.WriteLine("****************Set<T>***************");
                //set仅仅是个集合,无序,但是元素具有唯一性
                //hash分布,元素间没有关系,动态增加容量
                //应用:统计IP/IP投票/二次好友/粉丝合集   交叉并补
                HashSet<string> hashSet = new HashSet<string>();
                hashSet.Add("one");
                hashSet.Add("two");
                hashSet.Add("three");
                hashSet.Add("four");
                hashSet.Add("five");
                hashSet.Add("six");
                hashSet.Add("six");
                hashSet.Add("six");
                foreach (var item in hashSet)
                {
                    Console.WriteLine(item);
                }
                Console.WriteLine(hashSet.Count);
                Console.WriteLine(hashSet.Contains("two"));
                HashSet<string> hashSet1 = new HashSet<string>();
                hashSet1.Add("four");
                hashSet1.Add("five");
                hashSet1.Add("six");
                hashSet1.Add("seven");
                hashSet1.Add("eight");
                hashSet1.Add("nine");
                hashSet1.Add("ten");

                hashSet1.SymmetricExceptWith(hashSet);//对称差集
                hashSet1.UnionWith(hashSet);//并
                hashSet1.ExceptWith(hashSet);//差
                hashSet1.IntersectWith(hashSet);//交
            }
            {
                Console.WriteLine("****************SortedSet<T>***************");
                //SortedSet 排序的集合,
                //每进来一个元素都排一次序
                //应用:排行榜
                SortedSet<string> sortedSet = new SortedSet<string>();
                //IComparer<T> comparer  自定义排序用这个,比较器
                sortedSet.Add("123");
                sortedSet.Add("12");
                sortedSet.Add("1234");
                sortedSet.Add("234");
                sortedSet.Add("234");
                foreach (var item in sortedSet)
                {
                    Console.WriteLine(item);
                }
                Console.WriteLine(sortedSet.Count);
                Console.WriteLine(sortedSet.Contains("two"));
            }
            #endregion

            #region Key--Value
            {
                Console.WriteLine("****************Hashtable***************");
                //Hashtable,key-value读取快,增删也快,基于数组实现的
                //体积动态增加,拿key散列计算得到一个地址索引,数据存储在这个地址上,
                //如果有数据(散列冲突)地址+1;数据量不宜太大(3W条?),避免散列冲突太多
                //删除时也是计算出地址,直接对这个地址操作
                //空间有浪费;空间换时间
                //装箱拆箱
                Hashtable hashtable = new Hashtable();
                hashtable.Add("123", "小王");
                hashtable[234] = 999;
                hashtable[234] = 888;
                hashtable[21] = 66;
                hashtable["xiaowang"] = "小高";
                foreach (DictionaryEntry item in hashtable)
                {
                    Console.WriteLine(item.Key.ToString() + "--" + item.Value.ToString());
                }
                //线程安全
                Hashtable safeHashtable = Hashtable.Synchronized(hashtable);//一个线程写,多个线程读
            }
            {
                Console.WriteLine("****************Dictionary<T,T>***************");
                //字典  泛型,字典不是线程安全的,线程安全是:ConcurrentDictionary
                Dictionary<int, string> dic = new Dictionary<int, string>();
                dic.Add(1, "123");
                dic.Add(5, "13");
                dic.Add(4, "3");
                dic.Add(2, "12");
                dic.Add(3, "1");
                dic[4] = "小王";
                foreach (var item in dic)
                {
                    Console.WriteLine(item.Key + "--" + item.Value);
                }
            }
            {
                Console.WriteLine("****************SortedDictionary<T,T>***************");
                //SortedDictionary字典  有序的字典
                SortedDictionary<int, string> dic = new SortedDictionary<int, string>();
                dic.Add(1, "123");
                dic.Add(5, "13");
                dic.Add(4, "3");
                dic.Add(2, "12");
                dic.Add(3, "1");
                dic[4] = "小王";
                foreach (var item in dic)
                {
                    Console.WriteLine(item.Key + "--" + item.Value);
                }
            }
            {
                Console.WriteLine("****************SortedList<T,T>***************");
                SortedList<string, string> sortedList = new SortedList<string, string>();
                sortedList.Add("First", "Hello");
                sortedList.Add("Second", "World");
                sortedList.Add("Third", "!");
                sortedList["Third"] = "!!!";
                //sortedList.Add("Forth", "==");//add相同的可以报错
                sortedList.Add("Forth", "--");
                sortedList["Forth"] = "--";
                sortedList["Fifth"] = "//";

                var keyList = sortedList.Keys;
                var valueList = sortedList.Values;

                sortedList.TrimExcess();//减少内存开销
                sortedList.Remove("Third");
                sortedList.RemoveAt(0);
                sortedList.Clear();
            }
            #endregion

            #region 线程安全版本
            //ConcurrentQueue
            //ConcurrentStack
            //ConcurrentDictionary
            //ConcurrentBag<int> ts = new ConcurrentBag<int> { 1, 2, 3 };  //集合
            //BlockingCollection
            #endregion
        }
    }
}
using IteratorPattern.Iterator;
using IteratorPattern.Menu;
using System;
using System.Collections.Generic;

namespace IteratorPattern
{
    public class IteratorPattern
    {
        //1 迭代器模式 Iterator
        //2 .net的迭代器模式 yield return
        //3 延迟查询,按需获取
        public static void Show()
        {
            //KFC和MacDonal 两者的Foods数据结构差不多,都是集合,但是获取foods值的方式却不一样
            //一个是length,一个是count。我们更希望两者有共同的方式获取值
            //类似于数组和List都能foreach一样,数组和list都实现了迭代器
            //我们实现个类似于迭代器一样的东西,可以供KFC和MacDonal以共同方式遍历Foods
            {
                Console.WriteLine("********************KFC***********************");
                KFCMenu menu = new KFCMenu();
                Food[] foods = menu.GetFoods();
                for (int i = 0; i < foods.Length; i++)
                {
                    Console.WriteLine($"KFC:Id={foods[i].Id} Name={foods[i].Name} Price={foods[i].Price}");
                }

                foreach (var item in foods)
                {
                    Console.WriteLine($"KFC:Id={item.Id} Name={item.Name} Price={item.Price}");
                }

                //相同的遍历方式
                IIterator<Food> iterator = menu.GetEnumerator();
                while (iterator.MoveNext())
                {
                    Console.WriteLine($"KFC:Id={iterator.Current.Id} Name={iterator.Current.Name} Price={iterator.Current.Price}"); 
                }
            }
            {
                Console.WriteLine("********************MacDonal***********************");
                MacDonalMenu menu = new MacDonalMenu();
                List<Food> foods = menu.GetFoods();
                for (int i = 0; i < foods.Count; i++)
                {
                    Console.WriteLine($"KFC:Id={foods[i].Id} Name={foods[i].Name} Price={foods[i].Price}");
                }

                foreach (var item in foods)
                {
                    Console.WriteLine($"KFC:Id={item.Id} Name={item.Name} Price={item.Price}");
                }

                IIterator<Food> iterator = menu.GetEnumerator();
                while (iterator.MoveNext())
                {
                    Console.WriteLine($"KFC:Id={iterator.Current.Id} Name={iterator.Current.Name} Price={iterator.Current.Price}");
                }
            }
        }
    }
}
using IteratorPattern.Iterator;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Menu
{
    public class KFCMenu
    {
        private Food[] foods = new Food[3];

        public KFCMenu()
        {
            foods[0] = new Food()
            {
                Id = 1,
                Name = "汉堡",
                Price = 10
            };
            foods[1] = new Food()
            {
                Id = 1,
                Name = "可乐",
                Price = 8
            };
            foods[2] = new Food()
            {
                Id = 1,
                Name = "薯条",
                Price = 5
            };
        }

        public Food[] GetFoods()
        {
            return this.foods;
        }

        public IIterator<Food> GetEnumerator()
        {
            return new KFCMenuIterator(this);
        }
    }
}
using IteratorPattern.Iterator;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Menu
{
    public class MacDonalMenu
    {
        private List<Food> foods = new List<Food>();

        public MacDonalMenu()
        {
            foods.Add(new Food()
            {
                Id = 1,
                Name = "鸡腿",
                Price = 10
            });
            foods.Add(new Food()
            {
                Id = 1,
                Name = "冰淇淋",
                Price = 10
            });
            foods.Add(new Food()
            {
                Id = 1,
                Name = "鸡翅",
                Price = 10
            });
        }

        public List<Food> GetFoods()
        {
            return this.foods;
        }

        public IIterator<Food> GetEnumerator()
        {
            return new MacDonalMenuIterator(this);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Iterator
{
    public interface IIterator<T>
    {
        /// <summary>
        /// 当前对象
        /// </summary>
        T Current { get; }

        /// <summary>
        /// 移动到下个对象,是否存在
        /// </summary>
        /// <returns></returns>
        bool MoveNext();

        /// <summary>
        /// 重置
        /// </summary>
        void Reset();
    }
}
using IteratorPattern.Menu;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Iterator
{
    public class KFCMenuIterator : IIterator<Food>
    {
        private Food[] foods = null;

        public KFCMenuIterator(KFCMenu menu)
        {
            this.foods = menu.GetFoods();
        }

        private int _CurrentIndex = -1;
        /// <summary>
        /// 当前对象
        /// </summary>
        public Food Current
        {
            get
            {
                return this.foods[_CurrentIndex];
            }
        }

        /// <summary>
        /// 移动到下个对象,是否存在
        /// </summary>
        /// <returns></returns>
        public bool MoveNext()
        {
            return foods.Length > ++_CurrentIndex;
        }

        /// <summary>
        /// 重置
        /// </summary>
        public void Reset()
        {
            _CurrentIndex = -1;
        }
    }
}
using IteratorPattern.Menu;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Iterator
{
    public class MacDonalMenuIterator : IIterator<Food>
    {
        private List<Food> foods = null;

        public MacDonalMenuIterator(MacDonalMenu menu)
        {
            this.foods = menu.GetFoods();
        }

        private int _CurrentIndex = -1;
        /// <summary>
        /// 当前对象
        /// </summary>
        public Food Current
        {
            get
            {
                return this.foods[_CurrentIndex];
            }
        }

        /// <summary>
        /// 移动到下个对象,是否存在
        /// </summary>
        /// <returns></returns>
        public bool MoveNext()
        {
            return foods.Count > ++_CurrentIndex;
        }

        /// <summary>
        /// 重置
        /// </summary>
        public void Reset()
        {
            _CurrentIndex = -1;
        }
    }
}