单例设计模式(Singleton Pattern)
- 单例模式作用:
保证类在内存中只有一个对象
- 如何保证类在内存中只有一个对象呢?
- 控制类的创建,不让其他类来创建本类的对象。即私有化构造方法.
- 在本类中定义一个本类的对象。Singleton INSTANCE;
- 提供公共的访问方式。 public static Singleton getInstance(){return INSTANCE}
饿汉式
class Singleton { //1,私有构造函数 private Singleton(){} //2,创建本类对象 private static Singleton INSTANCE = new Singleton(); //3,对外提供公共的访问方法 public static Singleton getInstance() { return INSTANCE; } }
懒汉式, 单例的延迟加载模式
class Singleton { //1,私有构造函数 private Singleton(){} //2,声明一个本类的引用 private static Singleton INSTANCE; //3,对外提供公共的访问方法 public static Singleton getInstance() { //线程不安全 if(INSTANCE == null) INSTANCE = new Singleton(); return INSTANCE; } }
其他单例模式
//final修饰 class Singleton { //1,私有构造函数 private Singleton(){} //2,声明一个本类的引用,对外提供公共的访问方法 public static final Singleton INSTANCE = new Singleton(); } //静态内部类 class Singleton { private Singleton(){} private static class Create{ private static Singleton INSTANCE = new Singleton(); } public static Singleton getInstance(){ return Create.INSTANCE; } //枚举 enum Singleton { INSTANCE } //线程安全懒汉式 class Singleton { private Singleton() { } private static Singleton INSTANCE; public static Singleton getInstance() { //线程安全 if (INSTANCE == null) { synchronized (Singleton.class) { if (INSTANCE == null) { INSTANCE = new Singleton(); } } } return INSTANCE; } }
- 23种设计模式:
- 单例模式(Singleton Pattern)
- 工厂模式(Factory Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype Pattern)
- 适配器模式(Adapter Pattern)
- 桥接模式(Bridge Pattern)
- 组合模式(Composite Pattern)
- 装饰器模式(Decorator Pattern)
- 外观模式(Facade Pattern)
- 享元模式(Flyweight Pattern)
- 代理模式(Proxy Pattern)
- 责任链模式(Chain of Responsibility Pattern)
- 命令模式(Command Pattern)
- 解释器模式(Interpreter Pattern)
- 迭代器模式(Iterator Pattern)
- 中介者模式(Mediator Pattern)
- 备忘录模式(Memento Pattern)
- 观察者模式(Observer Pattern)
- 状态模式(State Pattern)
- 策略模式(Strategy Pattern)
- 模板模式(Template Pattern)
- 访问者模式(Visitor Pattern)
集合Collection
- 集合概述:
- 数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,而集合长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少.
- 子类:
ArrayList/LinkedList/HashSet/TreeSet
- 数组和集合的区别
- 数组既可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型(对象地址)
- 数组长度是固定的, 集合的长度的是可变的,可以根据元素的增加而增长
集合集成关系
集合中的方法
boolean add(E e) //增加,添加成功返回true boolean remove(Object o) //移除 void clear() //清空 boolean contains(Object o) //是否包含 boolean isEmpty() //true为空 int size() boolean addAll(Collection c)//true添加成功 boolean removeAll(Collection c) //true移除成功 boolean containsAll(Collection c) //是否包含 boolean retainAll(Collection c) //取交集,返回值true表示值有变化,false则值没变化 T[] toArray(T[] a); //集合转数组。数组转集合:Arrays.asList(T... arr); Iterator<E> iterator(); //用于集合遍历
集合的遍历
for/while循环遍历
ArrayList<Person> list = new ArrayList<>(); list.add(new Person("c", 5)); list.add(new Person("a", 3)); list.add(new Person("z", 54)); for (int i = 0; i < list.size(); i++) { Person person = list.get(i); }
增强for循环
for(元素数据类型 变量 : 数组或者Collection集合) { 使用变量即可,该变量就是元素 } //例子 ArrayList<String> list = new ArrayList<>(); list.add("zhang"); list.add("san"); list.add("lisi"); for (String s : list) { System.out.println(s); }
迭代器Iterator
boolean hasNext()
//是否有下一个
Object next()
//返回下一个元素ArrayList<String> list = new ArrayList<>(); list.add("张"); list.add("三"); list.add("李四"); Iterator<String> it = list.iterator(); while (it.hasNext()) { String next = it.next(); System.out.println(next); }
并发修改异常
ConcurrentModificationException
ArrayList<String> list = new ArrayList<>(); list.add("zhang"); list.add("san"); list.add("lisi"); Iterator<String> it = list.iterator(); while (it.hasNext()) { //用list的add/remove都会引起ConcurrentModificationException //list.remove("zhang"); list.add("wang"); String next = it.next(); System.out.println(next); }
解决并发修改异常
使用Iterator自带的remove方法,但没有add方法
ArrayList<String> list = new ArrayList<>(); list.add("zhang"); list.add("san"); list.add("lisi"); Iterator<String> it = list.iterator(); while (it.hasNext()) { String next = it.next(); if ("san".equals(next)) { it.remove(); } System.out.println(next); }
List(子类
ArrayList/LinkedList
)特有的迭代器:ListIterator<T> lit = list.listIterator();
ArrayList<String> list = new ArrayList<>(); list.add("zhang"); list.add("san"); list.add("lisi"); ListIterator<String> lit = list.listIterator(); while (lit.hasNext()) { String next = lit.next(); if ("san".equals(next)) { lit.remove(); } else { lit.add("MySon"); } System.out.println(next); } System.out.println(list);
List(子类
ArrayList/LinkedList
)集合特点有索引index
void add(int, E) //根据索引指定位置插入值 E set(int, E) //根据索引修改指定位置的值,返回被修改的值 E get(int) //根据索引找元素 E remove(int) //移除指定索引的值, 返回被移除的值 int indexOf(Object)//根据值返回索引
- 特有的迭代器:
ListIterator<T> lit = list.listIterator();
TreeSet集合特点
- 自动排序
保存的对象要实现
Comparable
接口或TreeSet构造方法传入Comparator
接口子类对象// 实现Comparable接口 public class Person implements Comparable<Person> { private String name; private int age; public Person(String name, int age) { this.age = age; this.name = name; } @Override public int compareTo(Person person) { return 0; } } // TreeSet构造方法传入Comparator接口子类对象 TreeSet<Person> set = new TreeSet<>(new Comparator<Person>() { @Override public int compare(Person person, Person t1) { return 0; } });
- 底层使用二叉树算法
- 数据唯一
- 不能存
null
HashSet集合特点
- 不可存重复数据,可存
null
- 没有固定顺序
- 不可存重复数据,可存
双列集合Map
概述
- 一个
Key
对应一个Value
- Key不可重复
- 子类:
HashMap/TreeMap
- 一个
Map与Collection的区别
- Map是双列的,Collection是单列的
- Map的键唯一,Collection的子体系Set是唯一的
- Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
方法
- a:添加
V put(K key,V value)
: 增加或替换
- 如果键是第一次存储,就直接存储元素,返回null
- 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
- b:删除
void clear()
:移除所有的键值对元素V remove(Object key)
:根据键删除键值对,并把值返回
- c:判断
boolean containsKey(Object key)
:判断集合是否包含指定的键boolean containsValue(Object value)
:判断集合是否包含指定的值boolean isEmpty()
:判断集合是否为空
- d:获取
Set<Map.Entry<K,V>> entrySet()
: 用于集合遍历Set<K> keySet()
:获取集合中所有键的集合,用于集合遍历V get(Object key)
:根据键获取值Collection<V> values()
:获取集合中所有值的集合int size()
:返回集合中的键值对的个数
- a:添加
Map集合遍历
根据键找值:
Set<K> keySet()
HashMap<String, Integer> hm = new HashMap<>(); hm.put("张三", 23); hm.put("李四", 24); hm.put("王五", 25); hm.put("赵六", 26); /*Set<String> keySet = hm.keySet(); //获取集合中所有的键 Iterator<String> it = keySet.iterator(); //获取迭代器 while(it.hasNext()) { //判断单列集合中是否有元素 String key = it.next(); //获取集合中的每一个元素,其实就是双列集合中的键 Integer value = hm.get(key); //根据键获取值 System.out.println(key + "=" + value); //打印键值对 }*/ for(String key : hm.keySet()) { //增强for循环迭代双列集合第一种方式 System.out.println(key + "=" + hm.get(key)); }
根据键值对对象找键和值:
Set<Map.Entry<K,V>> entrySet()
HashMap<String, Integer> hm = new HashMap<>(); hm.put("张三", 23); hm.put("李四", 24); hm.put("王五", 25); hm.put("赵六", 26); /*Set<Map.Entry<String, Integer>> entrySet = hm.entrySet(); //获取所有的键值对象的集合 Iterator<Entry<String, Integer>> it = entrySet.iterator();//获取迭代器 while(it.hasNext()) { Entry<String, Integer> en = it.next(); //获取键值对对象 String key = en.getKey(); //根据键值对对象获取键 Integer value = en.getValue(); //根据键值对对象获取值 System.out.println(key + "=" + value); }*/ for(Entry<String,Integer> en : hm.entrySet()) { System.out.println(en.getKey() + "=" + en.getValue()); }
- HashMap与TreeMap比较 (参考资料链接)
- HashMap里面存入的键值对在取出的时候是随机的,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。在Map 中插入、删除和定位元素,HashMap是最好的选择。
- TreeMap取出来的是排序后的键值对。插入、删除需要维护平衡会牺牲一些效率。但如果要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
- HashMap存取没有顺序,TreeMap按key排序。
集合排序
Collections
工具类boolean Collections.addAll(Collection c, T... elements); //添加数组,添加成功返回true void Collections.sort(List list); //排序,需实现Comparable接口 void Collections.sort(List list, Comparator c); //按Comparator条件排序 T Collections.min(Collection coll); //返回最小值 T Collections.min(Collection coll, Comparator comp);//按Comparator条件返回最小值 T Collections.max(Collection coll); //返回最大值 T Collections.max(Collection coll, Comparator comp);//按Comparator条件返回最大值 void Collections.shuffle(List list);//打乱 void Collections.reverse(List list);//反转
排序举例
ArrayList<Integer> list = new ArrayList<>(); list.add(4); list.add(10); list.add(5); list.add(2); list.add(44); Collections.sort(list, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { //返回int>=0则位置不变,int<0则交换位置 return o1 - o2; } }); System.out.println(list);
<完>