- 浏览: 7288 次
- 性别:
- 来自: 广州
最新评论
容器对象
1. 容器
1.1 泛型和类型安全
由于ArrayList等容器保存的是object类型.所以通过get()方法拿出来的对象还需要转型到你想要的类型,比如你定义储存Apple类对象的ArrayList容器appleList,你不但可以add Apple类型的对象,也可以add() Orange 类型的对象,因为无论是Apple类还是Orange类在放进容器里的时候已经向上转型为Object类型了.所以当程序运行时通过get方法,把本来是Orange类型强转型为Apple类型的时候就会抛出异常.
j2se5 引进泛型的机制,通过给容器指定类型,比如上述例子,ArrayList appleList<Apple>.这样编译器就会知道这个容器是专门储存Apple类,当add()方法储存Orange类时就会报错.
1.2 基本概念
1.2.1 Collection
独立元素
1.2.2 Map
键值对
1.3 添加一组元素
1.3.1 Arrays.asList()
接受一个数组或是一个用逗号分隔的元素列表(使用可变参数)
并将其转换为一个List对象
1.3.2 Collections.addAll()
接受一个Collections对象,以及一个数组或是一个用逗号分割的列表.
如:
1.3.3 Collection.addAll()
只能接受另外一个Collection元素作为参数,所以不如Array.asList()和Collections.addAll()灵活.
1.4 容器的打印
ArrayList和LinkedList从打印中看出,他们都属于顺序插入,区别在于性能上不同
HashSet,TreeSet,LinkedListSet都属于Set类型,每个相同的项只保存一次,从打印序列看出不同的set实现存储元素的方式不同
HashSet使用比较复杂的方法存储对象
TreeSet按照比较结果的升序存储对象
LinkedListSet按照被添加的顺序存储对象
本例使用3种风格的map,HashMap,TreeMap,LinkedHashMap
HashMap提供了最快的查找速度,但并没有按照顺序保存
TreeMap通过比较结果的升序保存键
LinkedHashMap通过添加顺序保存键,并同时保持了HashMap的速度
1.5 List
1.5.1 ArrayList
长于随机访问元素,但是在List中间插入和移除元素时较慢
(如果你开始在ArrayList中插入大量元素,并且你的元素开始变慢,这时你应该看看你的List实现可能会是罪魁闯祸手)
ps:发现此类瓶颈的最佳方式是仿真器,推介补充材料 http://MindView.net/Books/BetterJava
1.5.2 LinkedList
代价较低的插入和删除操作,优化了顺序访问,但是在随机访问方面比较慢,但是特性集比ArrayList大
1.5.2.1 Stack(以LinkedList实现)
堆栈 后进后出
示例:
1.5.2.1.1 push()
放入元素到栈中
1.5.2.1.2 peek()
只返回最顶层元素
1.5.2.1.3 pop()
返回最顶层元素并移除最顶层元素
1.5.2.2 Queue(以LinkedList实现)
先进先出
ps:这个规则应该是应用在等待时间最长的元素优先处理的例子
优先级队列声明下一个弹出元素是最需要的元素(具有最高的优先级)
1.5.3 常用的方法
1.5.3.1 contains()
确定某个对象是否在列表中
1.5.3.2 indexOf()
返回该对象在List中所处的位置
1.5.3.3 equals()
继承自object,根据类的不同比较的方法也有所不同
参见: subList(), retainAll(), removeAll()
1.5.3.3.1 retainAll()
返回两个集合中的有效的交集,这种行为依赖于equals方法
参见: equals()
1.5.3.3.2 removeAll()
删除对象列表含有的所有元素,同样通过equal()判断
参见: equals()
1.5.3.3.3 subList()
允许你从较大的列表中截出一个子列表,而这个子集无论排序怎样改变,父集.containsAll(子集)总是返回true
参见: equals()
1.5.3.4 toArray()
Collection通过toArray转换成一个数组
1.6 迭代器(Iterator)
是一种设计模式,在java里,Iterator是一个对象,只负责遍历并选择容器中的序列,而不用关心该序列底层是用什么实现的。
1.6.1 容器.iterator()
1.6.1.1 ListIterator
Iterator的子类,只能用于List类的访问,可以实现双向移动.
能够使用set方法替换过它最后一个访问的元素.
1.6.2 next()
1.6.3 hasNext()
1.6.4 remove()
1.7 Set
不保存其它元素
1.7.1 HashSet
1.8 HashMap
//以下的例子是随机数的值为键值,随机数出现的次数为值,实现对键值对的包装和拆包
1.8.1 多维Map
通过容器的组合,可以很容易将map扩展到多维map,比如下面的Map<Person,List<Pet>>
2. Collection和Iterator
一般来说,针对接口而非具体来编写代码可以应用于更多有相同的特征的对象模型.如编写的方法将接受一个Collection,那么该方法可以应用于任何实现了Collection的类.但是C++类库中并容器的任何公共基类,容器之间的所有特性通过迭代器实现.而在java中,这两种方法绑定在一起,即实现Collection就意味着需要提供iterator()方法
3. Foreach与迭代器
foreach主要用于数组,但在j2se5中引入了新的iterable的接口,并且该接口包含一个能够产生iterator的iterator()方法,并且Iterable能被foreach用来在序列中移动,任何实现了Iterable接口的类,都可以放在foreach语句中.
在下面是显示java所有环境变量的例子,由于Set是一个Iterable(),所以能使用foreach循环
如果想实现多种Iterable的遍历方式,比如添加一个倒序排序的iterable类,则可以使用设计模式中的迭代器模式.
1. 容器
1.1 泛型和类型安全
由于ArrayList等容器保存的是object类型.所以通过get()方法拿出来的对象还需要转型到你想要的类型,比如你定义储存Apple类对象的ArrayList容器appleList,你不但可以add Apple类型的对象,也可以add() Orange 类型的对象,因为无论是Apple类还是Orange类在放进容器里的时候已经向上转型为Object类型了.所以当程序运行时通过get方法,把本来是Orange类型强转型为Apple类型的时候就会抛出异常.
j2se5 引进泛型的机制,通过给容器指定类型,比如上述例子,ArrayList appleList<Apple>.这样编译器就会知道这个容器是专门储存Apple类,当add()方法储存Orange类时就会报错.
1.2 基本概念
1.2.1 Collection
独立元素
1.2.2 Map
键值对
1.3 添加一组元素
Collection<Integer> collection = new ArrayList<Integer>(Array.asList(1,2,3,4,5)); Integer[] moreInrs = {6,7,8,9,10}; collection.addAll(Arrays.asList(moreInts)); Collections.addAll(collection,11,12,13,14,15); Collections.addAll(collection,moreInts);
1.3.1 Arrays.asList()
接受一个数组或是一个用逗号分隔的元素列表(使用可变参数)
并将其转换为一个List对象
1.3.2 Collections.addAll()
接受一个Collections对象,以及一个数组或是一个用逗号分割的列表.
如:
1.3.3 Collection.addAll()
只能接受另外一个Collection元素作为参数,所以不如Array.asList()和Collections.addAll()灵活.
1.4 容器的打印
import java.util.*; public class PrintingContainers { static Collection fill(Collection<String> collection){ collection.add("rat"); collection.add("cat"); collection.add("dog"); collection.add("dog"); return collection; } static Map fill(Map<String,String> map){ map.put("rat","Fuzzy"); map.put("cat","Rags"); map.put("dog","Bosco"); map.put("dog","spot"); return map; } static void print(String collName,Collection collection){ System.out.println(collName+":"+collection); } static void print(String mapName,Map map){ System.out.println(mapName+":"+map); } public static void main(String[] args){ //List示例 print("ArrayList",fill(new ArrayList<String>())); print("LinkedList",fill(new LinkedList<String>())); //Set示例 print("HashSet",fill(new HashSet<String>())); print("TreeSet",fill(new TreeSet<String>())); print("LinkedHashSet",fill(new LinkedHashSet<String>())); //Map示例 print("HashMap",fill(new HashMap<String,String>())); print("TreeMap",fill(new TreeMap<String,String>())); print("LinkedHashMap",fill(new LinkedHashMap<String,String>())); } } /* Output: ArrayList:[rat, cat, dog, dog] LinkedList:[rat, cat, dog, dog] HashSet:[cat, dog, rat] TreeSet:[cat, dog, rat] LinkedHashSet:[rat, cat, dog] HashMap:{cat=Rags, dog=spot, rat=Fuzzy} TreeMap:{cat=Rags, dog=spot, rat=Fuzzy} LinkedHashMap:{rat=Fuzzy, cat=Rags, dog=spot} */
ArrayList和LinkedList从打印中看出,他们都属于顺序插入,区别在于性能上不同
HashSet,TreeSet,LinkedListSet都属于Set类型,每个相同的项只保存一次,从打印序列看出不同的set实现存储元素的方式不同
HashSet使用比较复杂的方法存储对象
TreeSet按照比较结果的升序存储对象
LinkedListSet按照被添加的顺序存储对象
本例使用3种风格的map,HashMap,TreeMap,LinkedHashMap
HashMap提供了最快的查找速度,但并没有按照顺序保存
TreeMap通过比较结果的升序保存键
LinkedHashMap通过添加顺序保存键,并同时保持了HashMap的速度
1.5 List
1.5.1 ArrayList
长于随机访问元素,但是在List中间插入和移除元素时较慢
(如果你开始在ArrayList中插入大量元素,并且你的元素开始变慢,这时你应该看看你的List实现可能会是罪魁闯祸手)
ps:发现此类瓶颈的最佳方式是仿真器,推介补充材料 http://MindView.net/Books/BetterJava
1.5.2 LinkedList
代价较低的插入和删除操作,优化了顺序访问,但是在随机访问方面比较慢,但是特性集比ArrayList大
1.5.2.1 Stack(以LinkedList实现)
堆栈 后进后出
示例:
import java.util.*; /* * 类名之后的<T>告诉编译器这将是一个参数化类型,是通用范型的应用,在运行时指定. */ public class Stack<T> { private LinkedList<T> storage = new LinkedList<T>(); public void push(T v){ storage.addFirst(v);} public T peek(){ return storage.getFirst();} public T pop() {return storage.removeFirst();} public boolean empty(){return storage.isEmpty();} public String toString(){return storage.toString();} }
public class StackTest { /** * 在实际应用中看出,Stack<String>指定给泛型T为String类型,同 理也可以指定为其它类型 */ public static void main(String[] args) { // TODO Auto-generated method stub Stack<String> stack = new Stack<String>(); for(String s:"My dog has fleas".split(" ")) stack.push(s); while(!stack.empty()) System.out.print(stack.pop()+" "); } }
1.5.2.1.1 push()
放入元素到栈中
1.5.2.1.2 peek()
只返回最顶层元素
1.5.2.1.3 pop()
返回最顶层元素并移除最顶层元素
1.5.2.2 Queue(以LinkedList实现)
先进先出
ps:这个规则应该是应用在等待时间最长的元素优先处理的例子
import java.util.LinkedList; import java.util.Queue; import java.util.Random; public class QueueDemo { /** * 这里用java.util库中已经实现好的queue做例子 */ public static void printQ(Queue queue){ while(queue.peek()!=null) System.out.print(queue.remove()+" "); System.out.println(); } public static void main(String[] args) { // TODO Auto-generated method stub Queue<Integer> queue = new LinkedList<Integer>(); Random rand = new Random(47); for(int i =0;i<10;i++) queue.offer(rand.nextInt(i+10)); printQ(queue); Queue<Character> qc =new LinkedList<Character>(); for(char c:"Brontosaurus".toCharArray()) qc.offer(c); printQ(qc); } }1.5.2.2.1 PriorityQueue
优先级队列声明下一个弹出元素是最需要的元素(具有最高的优先级)
import java.util.*; public class PriorityQueueDemo { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>(); Random rand = new Random(47); for(int i =0;i<10;i++) priorityQueue.offer(rand.nextInt(i+10)); QueueDemo.printQ(priorityQueue); /* * 如果是数字队列的话 priorityQueue会默认按数字从小到大排序,Collections.reverseOrder()为产生反序的Comparator * 通过重载Comparator方法来按照自己的形式作比较 */ List<Integer> ints = Arrays.asList(25,22,20,18,14,9,3,1,1,2,3,9,14,18,21,23,25); priorityQueue = new PriorityQueue<Integer>(ints); QueueDemo.printQ(priorityQueue); priorityQueue = new PriorityQueue<Integer>(ints.size(),Collections.reverseOrder()); priorityQueue.addAll(ints); QueueDemo.printQ(priorityQueue); /* * 从下面例子看出,空格也包含在字母比较的优先级内 */ String fact = "EDUCATION SHOULD ESCHEW OBFUSCATION"; List<String> strings = Arrays.asList(fact.split("")); PriorityQueue<String> stringPQ = new PriorityQueue<String>(strings); QueueDemo.printQ(stringPQ); stringPQ = new PriorityQueue<String>(strings.size(),Collections.reverseOrder()); stringPQ.addAll(strings); QueueDemo.printQ(stringPQ); //加入了hashset是为了消除重复元素作一个例子 Set<Character> charSet = new HashSet<Character>(); for(char c:fact.toCharArray()) charSet.add(c); PriorityQueue<Character> characterPQ = new PriorityQueue<Character>(charSet); QueueDemo.printQ(characterPQ); } }
1.5.3 常用的方法
1.5.3.1 contains()
确定某个对象是否在列表中
1.5.3.2 indexOf()
返回该对象在List中所处的位置
1.5.3.3 equals()
继承自object,根据类的不同比较的方法也有所不同
参见: subList(), retainAll(), removeAll()
1.5.3.3.1 retainAll()
返回两个集合中的有效的交集,这种行为依赖于equals方法
参见: equals()
1.5.3.3.2 removeAll()
删除对象列表含有的所有元素,同样通过equal()判断
参见: equals()
1.5.3.3.3 subList()
允许你从较大的列表中截出一个子列表,而这个子集无论排序怎样改变,父集.containsAll(子集)总是返回true
参见: equals()
1.5.3.4 toArray()
Collection通过toArray转换成一个数组
1.6 迭代器(Iterator)
是一种设计模式,在java里,Iterator是一个对象,只负责遍历并选择容器中的序列,而不用关心该序列底层是用什么实现的。
1.6.1 容器.iterator()
1.6.1.1 ListIterator
Iterator的子类,只能用于List类的访问,可以实现双向移动.
能够使用set方法替换过它最后一个访问的元素.
1.6.2 next()
1.6.3 hasNext()
1.6.4 remove()
1.7 Set
不保存其它元素
1.7.1 HashSet
1.8 HashMap
//以下的例子是随机数的值为键值,随机数出现的次数为值,实现对键值对的包装和拆包
import java.util.*; public class Statistics { public static void main(String[] args) { // TODO Auto-generated method stub Random rand = new Random(47); Map<Integer,Integer> m = new HashMap<Integer,Integer>(); for(int i = 0;i<10000;i++){ int r = rand.nextInt(40); Integer freq = m.get(r); m.put(r, freq == null?1:freq+1); //如果键不在map中,则freq返回null,表示第一次被找到,每次roll到相同的值则值递增并更新该键值对的值. } System.out.println(m); } }
1.8.1 多维Map
通过容器的组合,可以很容易将map扩展到多维map,比如下面的Map<Person,List<Pet>>
import java.util.*; import cn.edu.zen.eleven.container.*; public class MapOfList { public static Map<Person,List<? extends Pet>> petPeople = new HashMap<Person,List<? extends Pet>>(); static{ petPeople.put(new Person("Dawn"),Arrays.asList(new Cat(1,"black"),new Dog(2,"B&W"))); petPeople.put(new Person("Kate"), Arrays.asList(new Cat(3,"White"),new Cat(4,"Yellow"),new Dog(5,"Brown"))); } public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("People: "+petPeople.keySet()); System.out.println("Pets:"+petPeople.values()); /*Map可以返回它的Set,它的值的Collection,或它的键值对Set, keySet()方法产生了由petPeople中的所有键组成的Set.它在ForEach语句中被用来遍历Map */ for(Person person : petPeople.keySet()){ System.out.print(person + " has:"); for(Pet pet:petPeople.get(person)) System.out.print(" "+pet); System.out.println(); } } }
2. Collection和Iterator
一般来说,针对接口而非具体来编写代码可以应用于更多有相同的特征的对象模型.如编写的方法将接受一个Collection,那么该方法可以应用于任何实现了Collection的类.但是C++类库中并容器的任何公共基类,容器之间的所有特性通过迭代器实现.而在java中,这两种方法绑定在一起,即实现Collection就意味着需要提供iterator()方法
import java.util.*; public class InterfaceVsIterator { //Iterator和Collection都可以将display()方法与底层容器实现解耦 public static void display(Iterator<Pet> it){ while(it.hasNext()) System.out.print(it.next()); System.out.println(); } public static void display(Collection<Pet> pets){ for(Pet p:pets) System.out.print(p); System.out.println(); } public static void main(String[] args) { // TODO Auto-generated method stub List<Pet> petList = (List<Pet>) Pets.arrayList(); Set<Pet> petSet = new HashSet<Pet>(petList); Map<String,Pet> petMap = new LinkedHashMap<String,Pet>(); for(Pet pet:petList) petMap.put(pet.petName, pet); display(petList); display(petSet); display(petList.iterator()); display(petSet.iterator()); System.out.print(petMap); System.out.println(); System.out.print(petMap.keySet()); System.out.println(); display(petMap.values()); display(petMap.values().iterator()); } } //但是要实现一个不是Collection的外部类时,由于让它去实现Collection接口可能非常困难和麻烦,因此使用iterator会变得非常吸引人. import java.util.*; public class PetSequence { protected List<Pet> pets = Arrays.asList(new Pet(1,"Cat"),new Pet(2,"Dog"),new Pet(3,"Rabbit"),new Pet(4,"Fish"),new Pet(5,"Bird")); } public class NonCollectionSequence extends PetSequence { public Iterator<Pet> iterator(){ return new Iterator<Pet>(){ private int index = 0; public boolean hasNext(){ return index<pets.size(); } public Pet next(){return pets.get(index++);} public void remove(){ throw new UnsupportedOperationException(); } }; } public static void main(String[] args){ NonCollectionSequence nc =new NonCollectionSequence(); Iterator it =nc.iterator(); while(it.hasNext()) System.out.println(it.next()); } }
3. Foreach与迭代器
foreach主要用于数组,但在j2se5中引入了新的iterable的接口,并且该接口包含一个能够产生iterator的iterator()方法,并且Iterable能被foreach用来在序列中移动,任何实现了Iterable接口的类,都可以放在foreach语句中.
import java.util.Iterator; public class IterableClass implements Iterable<String> { protected String[] words = ("And that is how"+" we know the Earth to be banana-shaped.").split(" "); public Iterator<String> iterator() { return new Iterator<String>(){ private int index = 0; public boolean hasNext(){ return index<words.length; } public String next(){ return words[index++];} public void remove(){ throw new UnsupportedOperationException(); } }; } public static void main(String[] args){ for(String s:new IterableClass()) System.out.print(s+" "); } }
在下面是显示java所有环境变量的例子,由于Set是一个Iterable(),所以能使用foreach循环
//: holding/EnvironmentVariables.java import java.util.*; public class EnvironmentVariables { public static void main(String[] args) { for(Map.Entry entry: System.getenv().entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } } /* (Execute to see output) *///:~3.1 适配器方法惯用法
如果想实现多种Iterable的遍历方式,比如添加一个倒序排序的iterable类,则可以使用设计模式中的迭代器模式.
import java.util.*; public class MultiIterableClass extends IterableClass { public Iterable<String> reversed() { return new Iterable<String>() { public Iterator<String> iterator() { return new Iterator<String>() { int current = words.length - 1; public boolean hasNext() { return current > -1; } public String next() { return words[current--]; } public void remove() { // Not implemented throw new UnsupportedOperationException(); } }; } }; } /* 注意randomize()并没有返回它自己的Iterator,只返回被打乱顺序的List中的Iterator.Collection.shuffe()方法并没有打乱原来的数组,因为randomized方法将Arrays.asList()的结果包装起来.相当于备份了一个list的副本上打乱顺序 */ public Iterable<String> randomized() { return new Iterable<String>() { public Iterator<String> iterator() { List<String> shuffled = new ArrayList<String>(Arrays.asList(words)); Collections.shuffle(shuffled, new Random(47)); return shuffled.iterator(); } }; } public static void main(String[] args) { MultiIterableClass mic = new MultiIterableClass(); for(String s : mic.reversed()) System.out.print(s + " "); System.out.println(); for(String s : mic.randomized()) System.out.print(s + " "); System.out.println(); for(String s : mic) System.out.print(s + " "); } }
相关推荐
Java基础类型,容器,并发,IO流,面向对象,Web编程等代码总结。 2、分类文档 JVM虚拟机 JVM特点,结构与执行周期 JVM类加载机制 JVM运行时区数据 JVM执行引擎和垃圾回收 基础语法 理解Java中对象基础Object类 ...
本资料开源与IT开发者 论坛,由创建者:iyangxin 编写,本人只做了整理,如有疑惑请联系原作者。http://www.it619.net/ Java基础,JAVA简介 基础语法 数组 常用类 容器 面向对象 递归 多线程
《java程序设计》课程的题库资料,由贺州学院整理,可供学生期末课程复习使用,也可以供相关任课教师出卷使用。 内容示例为: 40. __________包包含了Collection的接口的类的API。 答案:Java.util 41. Math.round...
java各知识点详细总结(毕向东笔记整理)。第一章:编程基础 3-11 第二章:数组 11 -31 第三章:面向对象程序开发 31 -74 第四章:异常机制 74 -89 第五章:多线程技术 89 -122122122 第六章:常用类 API 122API 122 ...
JAVA实用类库提供了一套容器类,其中基本的类型是List,Set,Queue和Map。也称为集合类? 可以将任意数量的对象放置到容器中? JAVA中的容器都是类,也是说JAVA没有直接的关键字支持 泛型 泛型指定了...
javaspring面试题链接以及java基础的一些资料Spring的三大核心思想:IOC(控制反转),DI(依赖注入),AOP(面向切面编程)。 (1)IOC(控制反转) 实现将组件间的关系从程序内部提到外部容器(spring的xml)...
包含Java 基础,容器,多线程,反射,对象拷贝,Java Web,异常,网络,设计模式,Spring/Spring MVC,Spring Boot/Spring Cloud,Hibernate,Mybatis,RabbitMQ,Kafka,Zookeeper,MySql,Redis,JVM等知识点208道...
本资料开源与IT开发者 论坛,由创建者:iyangxin 编写,本人只做了整理,如有疑惑请联系原作者。http://www.it619.net/ Java基础,JAVA简介 基础语法 数组 常用类 容器 面向对象 递归 多线程 GUI 反射机制详解 正则...
面试题包括以下十九部分:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql...
分为十九个模块,分别是:「Java 基础、容器、多线程、反射、对象拷贝、Java Web 、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、MySQL、...
总共包含十九个模块,分别是: Java 基础、容器、多线程、反射、对象拷 贝、Java Web 、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、...
StudyJavaJava Basics1.java 基础学习2.java变成思想和java核心技术整理3.java8等java新特性学习整理###Java编程思想第1章 对象导论1.1 抽象过程1.2 每个对象都有一个接口1.3 每个对象都提供服务1.4 被隐藏的具体...
Java EE 5 应用服务器内部以及 Java 标准版 (Java SE) 5 应用程序中的 EJB 容器外部均可使用)将 Java 对象映射到关系数据库表。 在 JPA 之前,Java EE 应用程序将持续类表示为容器管理的实体 bean。使用 JPA,您...
标记整理算法(Mark-Compact).................................................................................................. 28 分代收集算法 ..............................................................
一、Java基础知识 1.Java有那些基本数据类型,String是不是基本数据类型,他们有何区别。 2.字符串的操作: 写一个方法,实现字符串的反转,如:输入abc,输出cba 写一个方法,实现字符串的替换,如:输入...
包含Java 基础,容器,多线程,反射,对象拷贝,Java Web,异常,网络,设计模式,Spring/Spring MVC,Spring Boot/Spring Cloud,Hibernate,Mybatis,RabbitMQ,Kafka,Zookeeper,MySql,Redis,JVM等知识点
把部分和整体的关系用树形结构来表示,从而使客户端可以使用统一的方式处理部分对象和整体对象。就像是图书管理员对图书馆的书籍进行整理,既可以对每一部分的书籍进行整理,也可以一次性将它们收集起来然后进行整理...