C#知识点-14(索引器、foreach的循环原理、泛型、委托)

news2024/11/16 18:33:29

索引器

概念:索引器能够让我们的对象,以索引(下标)的形式,便捷地访问类中的集合(数组、泛型集合、键值对)
应用场景:
1、能够便捷地访问类中的集合
2、索引的数据类型、个数、顺序不固定的时候
索引器与数组的比较:
        索引器的索引值(index)类型不受限制
索引器与属性的比较:
        a、索引器可以被重载,属性不能
        b、索引器不能声明为static,属性可以

    internal class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();
            Console.WriteLine(p[0]);
            Console.WriteLine(p[1]);
            p[2] = "张飞";
            Console.WriteLine(p[2]);
            Console.WriteLine(p["张三"]);
            Console.WriteLine(p["李四"]);
            p["王五"] = 100;
            Console.WriteLine(p["王五"]); ;
            Console.ReadKey();
            Console.ReadKey();
        }

    }
    class Person
    {
        //私有字段存储数组
        private string[] names = { "张三", "李四", "王五", "赵六", "田七" };
        //键值对
        private Dictionary<string, int> dic = new Dictionary<string, int>();
        //在构造函数里给键值对添加数据
        public Person()
        {
            dic.Add("张三", 1);
            dic.Add("李四", 2);
            dic.Add("王五", 3);
            dic.Add("赵六", 4);
        }

        //索引器
        //string:表示通过索引器获取数据的类型
        //this:表示索引器的名字,必须是this,不能修改
        //index:索引的类型
        public string this[int index]
        {
            get { return names[index]; }//通过索引取得数组中的值
            set { names[index] = value; }//给数组中的某个元素赋值
        }

        //索引器是可以重载的
        public int this[string key]
        {
            get { return dic[key]; }
            set { dic[key] = value; }
        }
    }
    

索引器案例

    internal class Program
    {
        //根据员工的姓名、编号,查找员工所在部门。
        //根据员工的姓名、部门,查找员工的编号。
        //根据员工的部门、编号,查找员工的姓名。
        static void Main(string[] args)
        {
            EmployeeIndexer emps = new EmployeeIndexer();
            string dep = emps["张三", 1];
            if (!string.IsNullOrEmpty(dep))
            {
                Console.WriteLine(dep);
            }
            else
            {
                Console.WriteLine("查无此人");
            }

            int? id = emps["李四", "研发部"];
            if (id != null)
            {
                Console.WriteLine(id);
            }
            else
            {
                Console.WriteLine("查无此人");
            }

            Console.ReadKey();
        }
        class Employee  //员工类
        {
            public string Name { get; set; } //员工姓名
            public int ID { get; set; } //员工编号
            public string Department { get; set; }  //员工部门
            public Employee(string name, int iD, string department)
            {
                this.Name = name;
                this.ID = iD;
                this.Department = department;
            }
        }
        class EmployeeIndexer   //员工的索引类,负责对员工信息进行精确的查询
        {
            private List<Employee> listEmps = new List<Employee>();
            public EmployeeIndexer()
            {
                listEmps.Add(new Employee("张三", 1, "行政部"));
                listEmps.Add(new Employee("李四", 2, "财务部"));
                listEmps.Add(new Employee("王五", 3, "研发部"));
                listEmps.Add(new Employee("赵六", 4, "人事部"));
            }

            //根据员工的姓名、编号,查找员工所在部门。
            public string this[string name,int id]
            {
                get
                {
                    for (int i = 0; i < listEmps.Count; i++)
                    {
                        if (listEmps[i].Name == name && listEmps[i].ID==id)
                        {
                            return listEmps[i].Department;
                        }
                    }
                    return null;
                }
            }
            //根据员工的姓名、部门,查找员工的编号。
            public int? this[string name, string dep]  // int?  ? 可空的值类型
            {
                get
                {
                    for (int i = 0; i < listEmps.Count; i++)
                    {
                        if (listEmps[i].Name == name && listEmps[i].Department == dep)
                        {
                            return listEmps[i].ID;
                        }
                    }
                    return null;

                }
            }

            //根据员工的部门、编号,查找员工的姓名。

            public string this[int id, string dep]
            {
                get
                {
                    for (int i = 0; i < listEmps.Count; i++)
                    {
                        if (listEmps[i].ID == id && listEmps[i].Department == dep)
                        {
                            return listEmps[i].Name;
                        }
                    }
                    return null;
                }
            }
        }
    }

foreach的循环原理

1、要被循环的对象,需要实现IEnumerable接口
2、需要给被循环的对象,创建一个遍历的对象,并且要实现IEnumerator接口
3、        Current:返回当前遍历到的数据元素
              MoveNext:判断时候可以继续向后循环,并改变index的值
              Reset:重置索引

通过代码实现foreach
    internal class Program
    {
        //foreach的循环原理
        //只有实现了IEnumerable这个接口的对象才能被foreach
        static void Main(string[] args)
        {
            Person p = new Person();
            //获取遍历Person对象的人
            IEnumerator enumerator = p.GetEnumerator();
            //开始遍历
            while (enumerator.MoveNext())
            {
                Console.WriteLine(enumerator.Current.ToString());
            }
            //IEnumerable :要被遍历的对象必须实现这个接口
            //IEnumerator: 遍历对象的迭代器对象,要实现
            Console.ReadKey();
            //或者可以直接使用foreach
            foreach (var item in p)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }



    }
    class Person : IEnumerable
    {
        //IEnumerable : 接口,表示可以被foreach遍历的能力
        //IEnumerator:真正做遍历集合这件事儿的人
        //GetEnumerator:获取做遍历集合这件事儿的人
        private string[] names = { "张三", "李四", "王五", "赵六", "田七" };
        public IEnumerator GetEnumerator()
        {
            return new PersonEnumerator(names);
        }
    }
    //枚举/迭代/遍历
    class PersonEnumerator : IEnumerator
    {
        string[] myNames;
        int index = -1;
        //构造函数:获取要遍历的真实数据
        public PersonEnumerator(string[] names)
        {
            this.myNames = names;
        }
        //Current表示返回当前遍历到的元素,object类型
        public object Current
        {
            //索引没有越界的情况
            get
            {
                if (index>=0&&index<this.myNames.Length)
                {
                    return this.myNames[index];
                }
                return null;//数组越界了
            }
        }

        //1、索引+1
        //2、判断是否可以继续向后移动(+1),
        //如果可以继续向后+1.则索引+1,并且返回true
        //如果不可以向后+1,返回false
        public bool MoveNext()
        {
            if (index+1<this.myNames.Length)
            {
                index++;
                return true;
            }
            else
            {
                return false;
            }
        }

        //重置索引,让索引回到原始位置
        public void Reset()
        {
            index= -1;
        }
    }

泛型

概念:在某些情况,我们不想使用特定的数据类型,可以使用泛型

    internal class Program
    {
        static void Main(string[] args)
        {
            Person<int> person = new Person<int>();
            person.SayHi(199);
            Person<string> person2 = new Person<string>();
            person2.SayHi("张三");
            Person<double> person3 = new Person<double>();
            person3.SayHi_2<string>(3.14, "李四");
            person3.SayHi_2(3.14);
            double d = person3.SayHi_3(11.11);
            Console.WriteLine(d);
            int n = person3.SayHi_4<int>(3.14, 100);
            Console.WriteLine(n);
            int n2 = person3.SayHi_5<int>(3.14);
            Console.WriteLine(n2);
            Console.ReadKey();
        }
    }
    //泛型类
    class Person<T>
    {
        public void SayHi(T t)
        {
            Console.WriteLine(t);
        }
        //泛型方法
        public void SayHi_2<K>(T t, K k)
        {
            Console.WriteLine(t);
            Console.WriteLine(k);
        }
        //泛型方法也可以重载
        public void SayHi_2(T t)
        {
            Console.WriteLine(t);
        }
        //返回值类型为T,参数为T
        public T SayHi_3(T t)
        {
            return t;
        }
        //返回值类型为K,参数为T和K
        public K SayHi_4<K>(T t, K k)
        {
            return k;
        }
        //返回值类型为K,参数为K
        public K SayHi_5<K>(K k)
        {
            return k;
        }

        //泛型方法中的返回值如何处理?
        //1、使用typeof关键字判断泛型的类型
        //2、使用object作为中间量进行强制转换
        //3、return defalut。default会返回数据类型的默认值
        public K SayHi_5<K>(T t)
        {
            K k;
            //如果k的类型是int
            if (typeof(K) == typeof(int))
            {
                return (K)(object)100;
            }
            else if (typeof(K) == typeof(string))
            {
                return (K)(object)"Hello World";
            }
            else if (typeof(K) == typeof(double))
            {
                return (K)(object)3.14;
            }
            else
            {
                //返回K类型的默认值
                return default;
            }
        }

        //泛型接口
        interface IFlayble<T>
        {
            void Fly(T t);
        }
        class Plane : IFlayble<string>
        {
            public void Fly(string t)
            {
                throw new NotImplementedException();
            }
        }
        class Bird : IFlayble<int>
        {
            public void Fly(int t)
            {
                throw new NotImplementedException();
            }
        }
    }

泛型约束

    internal class Program
    {
        static void Main(string[] args)
        {
            Person<int> person = new Person<int>();
            Student<Person<int>> student2 = new Student<Person<int>>();

            Teacher<Animal> t1 = new Teacher<Animal>();
            Teacher<Bird> t2 = new Teacher<Bird>();
            
            Plane<IFly> plane = new Plane<IFly>();
            Plane<MaQue> p2 = new Plane<MaQue>();

            Computer<int, IComparable> cpu = new Computer<int, IComparable>();
            Computer<FileStream, Stream> cpu2 = new Computer<FileStream, Stream>();

        }
    }
    //泛型约束
    //where 表示类型要符合的条件
    class Person<T> where T : struct  //值类型约束
    {

    }
    class Student<T> where T : class, new()        //引用类型约束
    {

    }

    class Animal { }
    class Bird : Animal { }
    interface IFly
    {
        void Fly();
    }
    class MaQue : IFly
    {
        public void Fly()
        {
        }
    }
    class Teacher<T> where T : Animal { }
    class Plane<T> where T : IFly { }
    class Computer<T, U> where T : U { }

委托

概念:把方法作为参数,传递给另一个方法
委托,就是一个方法的指针
声明委托:public delegate(委托的关键字) 返回值类型 委托名称(参数列表)
使用委托:创建委托对象,指向某一个跟委托签名一致的方法(签名:参数和返回值)
 

    internal class Program
    {
        public delegate void Del();//无参数无返回值的委托
        public delegate void Del2(string name);//参数为string的委托
        public delegate int Del3(string name, int age);//有两个参数,返回值为int类型的委托
        static void Main(string[] args)
        {
            //虽然在代码层面没有创建委托对象,但是编译器在编译的时候,依然会帮助我们创建一个委托对象
            //这个委托对象,在内存中指向M1方法
            Del del = M1;//等同于 Del del = new Del(M1);
            del(); //对M1方法的直接调用
            del.Invoke();//对方法的间接调用

            Del2 del2 = M2;
            del2("张三");
            del2.Invoke("李四");

            Del3 del3 = M3;//委托与他指向的方法签名,必须完全一致,M4的话会报错
            int res = del3("张三", 18);
            Console.WriteLine(res);


            Console.ReadKey();
        }

        static void M1()
        {
            Console.WriteLine("无参数无返回值的方法");
        }
        static void M2(string name)
        {
            Console.WriteLine("参数string,无返回值的方法");
            Console.WriteLine(name);
        }
        static int M3(string name,int age)
        {
            Console.WriteLine("两个参数,返回值为int的方法");
            Console.WriteLine(name);
            Console.WriteLine(age);
            return 100;
        }
        static int M4(int age,string name)
        {
            Console.WriteLine("和上面方法的参数类型不同");
            return 200;
        }
    }

委托案例


{
    public delegate string DelProStr(string str);
    internal class Program
    {
        static void Main(string[] args)
        {
            //处理字符串数组
            //1、给字符串数组的两边,添加双引号
            //2、给字符串数组全部转换为大写
            //3、给字符串数组全部转换为小写


            string[] names = { "Jay", "James", "green", "blue" };
            //SYH(names);
            //StrToUpper(names);
            //StrToLower(names);

            ProcessStr(names, StrToSYH);
            ProcessStr(names, StrToUpper);
            foreach (var item in names)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }

        static void ProcessStr(string[] names, DelProStr del)
        {
            for (int i = 0; i < names.Length; i++)
            {
                names[i] = del(names[i]);
            }
        }

        static string StrToSYH(string str)
        {
            return "\"" + str + "\"";
        }

        static string StrToUpper(string str)
        {
            return str.ToUpper();
        }

        static string StrToLower(string str)
        {
            return str.ToLower();
        }


        把数组中的每一个元素,加双引号
        //static void SYH(string[] names)
        //{
        //    for (int i = 0; i < names.Length; i++)
        //    {
        //        names[i] = "\"" + names[i] + "\"";
        //    }
        //}
        把数组中的每一个元素,转成大写
        //static void StrToUpper(string[] names)
        //{
        //    for (int i = 0; i < names.Length; i++)
        //    {
        //        names[i] = names[i].ToUpper();
        //    }
        //}

        把数组中的每一个元素,转成小写
        //static void StrToLower(string[] names)
        //{
        //    for (int i = 0; i < names.Length; i++)
        //    {
        //        names[i] = names[i].ToLower();
        //    }
        //}

    }
}

使用委托计算两个数的最大值


{

    public delegate int DelCompare<T>(T o1, T o2); //比较o1和o2的值  让o1-o2  >  0

    internal class Program
    {
        static void Main(string[] args)
        {
            //求数组的最大值  int  string  Person
            int[] numbers = { 1, 2, 3, 43, 45 };
            string[] names = { "ab", "James", "abcdefg" };
            Person[] pers = { new Person() { Name = "张三", Age = 19 }, new Person() { Name = "李四", Age = 20 }, new Person() { Name = "王五", Age = 22 } };

            int max = GetMax(numbers, GetIntMax);
            string max2 = GetMax(names, GetStringMax);
            Person max3 = GetMax(pers, GetPersonMax);
            Console.WriteLine(max3.Name);
            Console.WriteLine(max2);
            Console.ReadKey();
        }


        static T GetMax<T>(T[] nums, DelCompare<T> del)  //不同点1:返回值不一样  不同点2:参数不一样  不同点3:比较的方式不一样
        {
            T max = nums[0];
            for (int i = 0; i < nums.Length; i++)
            {
                //nums[i] > max
                if (del(nums[i], max) > 0) //比较的方式,因为要比较的数据类型是不一样的,所以比较的方式也是不一样的。
                {
                    max = nums[i];
                }
            }
            return max;
        }

        static int GetIntMax(int o1, int o2)
        {
            //值类型---->引用类型:装箱   
            //int n1 = (int)o1;
            //int n2 = (int)o2;
            return o1 - o2;
        }

        static int GetStringMax(string o1, string o2)
        {
            //string s1 = (string)o1;
            //string s2 = (string)o2;
            return o1.Length - o2.Length;
        }

        static int GetPersonMax(Person o1, Person o2)
        {
            //Person p1 = (Person)o1;
            //Person p2 = (Person)o2;
            return o1.Age - o2.Age;
        }

        //求整数类型数组的最大值
        //static int GetMax(int[] nums)  //不同点1:返回值不一样  不同点2:参数不一样  不同点3:比较的方式不一样
        //{
        //    int max = nums[0];
        //    for (int i = 0; i < nums.Length; i++)
        //    {
        //        if (nums[i] > max)
        //        {
        //            max = nums[i];
        //        }
        //    }
        //    return max;
        //}
        求字符串数组的最大值(字符串的长度)
        //static string GetMax(string[] names)
        //{
        //    string max = names[0];
        //    for (int i = 0; i < names.Length; i++)
        //    {
        //        if (names[i].Length > max.Length)
        //        {
        //            max = names[i];
        //        }
        //    }
        //    return max;
        //}

        求Person数组中,年龄最大的人
        //static Person GetMax(Person[] pers)
        //{
        //    Person max = pers[0];
        //    for (int i = 0; i < pers.Length; i++)
        //    {
        //        if (pers[i].Age > max.Age)
        //        {
        //            max = pers[i];
        //        }
        //    }
        //    return max;
        //}
    }

    class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }
    }
}

使用lambda表达式简化上述代码

    public delegate int DelCompare<T>(T o1, T o2);//比较o1和o2的值
    internal class Program
    {
        static void Main(string[] args)
        {
            //求数组的最大值 int string Person
            int[] numbers = { 1, 2, 3, 4, 5 };
            string[] names = { "ab", "abc", "avcdsf" };
            Person[] pers = { new Person() { Name = "张三", Age = 18 }, new Person() { Name = "李四", Age = 20 }, new Person() { Name = "王五", Age = 25 } };

            //调用泛型方法
            int intMax = GetMax<int>(numbers, (a, b) => { return a - b; });//lambda表达式:方法的极致的简化写法
            Console.WriteLine(intMax);
            string stringMax = GetMax(names, (a, b) => { return a.Length-b.Length; });
            //如果后面的参数,都是并且只有一个T,则<>可以省略,当你填入第一个参数的时候,所有的T就已经确定了
            Console.WriteLine(stringMax);
            Person personMax = GetMax(pers, (a, b) => { return a.Age-b.Age; });
            Console.WriteLine(personMax.Name);
            Console.ReadKey();
        }

        //写一个泛型方法,用于计算任意类型数组的最大值
        static T GetMax<T>(T[]nums,DelCompare<T> del)
        {
            T max = nums[0];
            for (int i = 0; i < nums.Length; i++)
            {
                if (del(nums[i],max)>0)
                {
                    max = nums[i];
                }
            }
            return max;
        }
    }
    class Person
    {
        public int Age { get; set; }
        public string Name { get; set;}
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1461841.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从源码解析Kruise(K8S)原地升级原理

从源码解析Kruise原地升级原理 本文从源码的角度分析 Kruise 原地升级相关功能的实现。 本篇Kruise版本为v1.5.2。 Kruise项目地址: https://github.com/openkruise/kruise 更多云原生、K8S相关文章请点击【专栏】查看&#xff01; 原地升级的概念 当我们使用deployment等Wor…

vue:find查找函数实际开发的使用

find的作用&#xff1a; find 方法主要是查找数组中的属性&#xff0c;会遍历数组&#xff0c;对每一个元素执行提供的函数&#xff0c;直到找到使该函数返回 true 的元素。然后返回该元素的值。如果没有元素满足测试函数&#xff0c;则返回 undefined。 基础使用&#xff1a…

摄像头相机标定

相机标定 相机标定的目的有两个。 第一&#xff0c;要还原摄像头成像的物体在真实世界的位置就需要知道世界中的物体到计算机图像平面是如何变换的&#xff0c;相机标定的目的之一就是为了搞清楚这种变换关系&#xff0c;求解内外参数矩阵。 第二&#xff0c;摄像机的透视投影有…

linux下开发,stm32和arduino,我该何去何从?

linux下开发&#xff0c;stm32和arduino&#xff0c;我该何去何从&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「stm3的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共…

zemax消畸变目镜

用三胶合透镜代替了RKE的消色差双胶合镜&#xff0c;减少了横向色差和畸变 入瞳直径4mm波长0.51、0.56、0.61半视场22.5焦距28mm 镜头参数&#xff1a; 成像效果&#xff1a; 畸变效果&#xff1a; 点列图&#xff1a;

S281 LoRa网关助力智慧城市建设的智能交通管理

S281 LoRa网关作为智慧城市建设中的重要组成部分&#xff0c;发挥着关键的作用&#xff0c;特别是在智能交通管理方面。通过连接各类传感器设备和物联网终端&#xff0c;S281 LoRa网关实现了对城市交通系统的远程监控、智能调度和信息化管理&#xff0c;为城市交通管理部门提供…

UE5 摄像机晃动

1.新建camerashake蓝图类 命名为 晃动 2.调节相关参数 3.打开关卡序列 给摄像机添加 晃动 动画 4.播放

#gStore-weekly | workbench功能详解之知识更新

gStore workbench作为gStore的可视化管理工具&#xff0c;不仅提供了可视化查询功能&#xff0c;还提供了可视化的知识更新功能&#xff0c;用户可以在可视化界面上进行知识的新增、修改和删除等操作&#xff0c;让我们的知识管理更加清晰和便捷。 1.查询知识 登录workbenc…

新年伊始,VR全景释放“强信号”,可以结合哪些行业?

一年之计在于春&#xff0c;各行各业都想抢占在经济的第一线&#xff0c;那么如何抓住新一轮科技革命和产业变革新机遇呢&#xff1f;VR全景释放了“强信号”。对于大部分实体行业来说&#xff0c;都会有VR全景的制作需求&#xff0c;租房买房的&#xff0c;可能都见识过线上VR…

Manacher算法和扩展kmp

Manacher算法 a情况 b情况 具体例子 c情况 总结 代码 #include<iostream> #include<algorithm> #include<string> #include<cmath>using namespace std; const int N 1.1e7 1; char ss[N << 1]; int p[N << 1]; int n; void manacherss…

Qt应用-视频播放器实例

本文讲解Qt视频播放器应用实例。 实现功能 视频的播放暂停、拖动进度控制,声音控制播放列表控制播放区域的暂停控制,全屏控制等。 界面设计 <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"><class>frmVide…

c#高级-正则表达式

正则表达式是由普通字符和元字符&#xff08;特殊符号&#xff09;组成的文字形式 应用场景 1.用于验证输入的邮箱是否合法。 2.用于验证输入的电话号码是否合法。 3.用于验证输入的身份证号码是否合法。等等 正则表达式常用的限定符总结&#xff1a; 几种常用的正则简写表达式…

微服务篇之注册中心

一、eureka 1.eureka的作用 2.eureka工作流程 1. 服务提供者和服务消费者向注册中心注册服务信息&#xff0c;然后注册中心记录了对应的服务器地址。 2. 服务消费者从注册中心拉取服务提供者的信息。 3. 通过负载均衡找到对应的服务提供者地址。 4. 服务消费者远程调用对应的服…

评估睡眠阶段分类:年龄和早晚睡眠对分类性能的影响

摘要 睡眠阶段分类是专家用来监测人类睡眠数量和质量的常用方法&#xff0c;但这是一项耗时且费力的任务&#xff0c;观察者之间和观察者内部的变异性较高。本研究旨在利用小波进行特征提取&#xff0c;采用随机森林进行分类&#xff0c;寻找并评估一种自动睡眠阶段分类的方法…

C#知识点-13(进程、多线程、使用Socket实现服务器与客户端通信)

进程 定义&#xff1a;每一个正在运行的应用程序&#xff0c;都是一个进程 进程不等于正在运行的应用程序。而是为应用程序的运行构建一个运行环境 Process[] pros Process.GetProcesses();//获取电脑中所有正在运行的进程//通过进程&#xff0c;直接打开文件//告诉进程&…

ChatGPT丨成像光谱遥感技术中的AI革命:ChatGPT应用指南

遥感技术主要通过卫星和飞机从远处观察和测量我们的环境&#xff0c;是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型&#xff0c;在理解和生成人类语言方面表现出了非凡的能力。本课程重点介绍ChatGPT在遥感中的应用&#xff0c;人工智…

前端构建效率优化之路

项目背景 我们的系统&#xff08;一个 ToB 的 Web 单页应用&#xff09;前端单页应用经过多年的迭代&#xff0c;目前已经累积有大几十万行的业务代码&#xff0c;30 路由模块&#xff0c;整体的代码量和复杂度还是比较高的。 项目整体是基于 Vue TypeScirpt&#xff0c;而构…

18. 四数之和 - 力扣(LeetCode)

问题描述 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元组元素一一对应&#xff0c;则认为两个四元组重复&#xff09;&#xff1a; …

如何实现多级缓存?

冗余设计是在系统或设备完成任务起关键作用的地方&#xff0c;增加一套以上完成相同功能的功能通道&#xff08;or 系统&#xff09;、工作元件或部件&#xff0c;以保证当该部分出现故障时&#xff0c;系统或设备仍能正常工作&#xff0c;以减少系统或者设备的故障概率&#x…

板块一 Servlet编程:第七节 ServletContext对象全解与Servlet三大域对象总结 来自【汤米尼克的JAVAEE全套教程专栏】

板块一 Servlet编程&#xff1a;第七节 ServletContext对象全解与Servlet三大域对象总结 一、什么是ServletContext对象二、获取ServletContext对象及常用方法&#xff08;1&#xff09;获取 ServletContext 对象&#xff08;2&#xff09;ServletContext对象提供的方法 三、se…