大家好,欢迎来到IT知识分享网。
笔记
一、简介
- Java标准库自带的
java.util
包提供了集合类:Collection
。它是除Map外所有其他集合类的根接口。 - Java主要包括以下三种集合:
List
:一种有序列表的集合。Set
:一种保证没有重复元素的集合。Map
:一种通过键值(key-value)查找的映射表集合。
- 存在一些历史遗留类,尽量不要去使用:
Hashtable
:一种线程安全的Map实现;Vector
:一种线程安全的List实现;Stack
:基于Vector实现的LIFO的栈。Enumeration<E>
:已被Iterator取代。
二、List
-
List类就像数组一样,提供两个实现:
- ArrayList(数组实现)
- LinkedList(链表实现)
-
具体区别:
-
LinkedList 即实现了
List
接口,又实现了Queue
接口。 -
of()
方法:jdk9之后才开始存在。List.of(1, 2, "1", true);
-
我们应当坚持使用迭代器==
iterator
或者forEach
==循环遍历 List,因为它俩总能根据不同的类型提供最快的遍历速度。 -
Iterator对象有两个方法:
boolean hasNext()
判断是否有下一个元素E next()
返回下一个元素
-
数组与 List 之间的相互转换:
- 数组转 List (两种方法):
Integer[] num={ 1,2,3}; // 1. asList() List<Integer> list = Arrays.asList(num); // 2. of() List<Integer> list = List.of(num);
- List 转数组:
List<Integer> list = List.of(1,2,3); // toArray()的参数标识:类型 + 大小 Integer[] array = list.toArray(new Integer[list.size()]);
三、Map
-
Map 跟 List一样,只是一个接口,最常用的实现类是
HashMap
。 -
HashMap不保证数据存储的顺序,TreeMap保证。
-
如果 key 不存在,将返回 null。
-
简单遍历 Map
- ==
keySet()
==遍历:
Map<Integer,String > maps=new HashMap<>(); maps.put(1,"a");maps.put(2,"b");maps.put(3,"c"); for (Integer key:maps.keySet()){ String value = maps.get(key); System.out.println(value); }
- ==
entrySet()
==遍历
Map<Integer,String > maps=new HashMap<>(); maps.put(1,"a");maps.put(2,"b");maps.put(3,"c"); for (Map.Entry<Integer, String > map : maps.entrySet()){ System.out.println(map.getKey()+map.getValue()); }
- ==
-
HashMap原理
- 内部使用数组,数组长度总是 2n(初始大小为16。创建时可以手动指定,以免频繁扩容,但是当指定为1000时,容量并不是真正的1000,而是210 = 1024 ),通过计算 key 的 hashCode( ) 直接定位 value 所在的索引。
- 空间换时间
- 如果key的值为”a”,计算得到的索引总是1,因此返回value为Person(“Xiao Ming”),这样就不必遍历整个数组,即可直接读取key对应的value。(内部的一套指定算法)
-
EnumMap:一种基于枚举类的 Map。
-
TreeMap
- 基于接口SortedMap,不使用
equals()
和hashCode()
(因为有序无需此)。 - 有序,会在内部对Key进行排序。(放入的Key必须实现 Comparable 接口,如果作为Key的class没有实现Comparable接口,那么必须在创建TreeMap时同时指定一个自定义排序算法)
Map<Person, Integer> map = new TreeMap<>(new Comparator<Person>() { public int compare(Person p1, Person p2) { return p1.name.compareTo(p2.name); } });
- 基于接口SortedMap,不使用
-
Properties
- 一种特殊的 Map ,主要用来读写配置文件。
- 内部本质上是一个
Hashtable
,它的设计实际上存在问题,但是为了保持兼容性,现在已经无法更改。
last_open_file = /data/hello.txt auto_save_interval = 60
- 读取步骤
- 创建实例;
- 调用
load()
读取文件; - 调用
getProperty()
获取配置。
String f = "setting.properties"; Properties props = new Properties(); // load()默认总是以ASCII编码读取字节流,所以会导致读到乱码 props.load(new FileReader("settings.properties", StandardCharsets.UTF_8)); String filepath = props.getProperty("last_open_file"); String interval = props.getProperty("auto_save_interval", "120");
- 写入步骤
Properties props = new Properties(); props.setProperty("url", "http://www.liaoxuefeng.com"); props.setProperty("language", "Java"); props.store(new FileOutputStream("./setting.properties"), "这是写入的注释");
四、Set
-
Set只是接口,具体实现有
hashSet
、TreeSet
(前者不保证顺序)。 -
Set用于存储不重复的元素集合,实际上相当于只存储key、不存储value的
Map
-
HashSet
仅仅是对HashMap的一个简单封装。 -
LinkedHashSet 继承自 HashSet ,具有 HashSet 的优点,内部使用链表维护了元素插入顺序。
五、Queue
-
Queue只是一个接口,具体的实现有PriorityQueue、Deque、Stack。
-
Queue接口定义了几个方法,分别为:
- int size():获取队列长度
- add() 或 offer():添加元素到队列:
- remove() / poll():获取队首元素并删除
- element() / peek() :获取队首元素但不删除
(注意到三次存在两种方法,不同之处在于)
throw Exception 返回false或null 添加元素到队尾 add(E e) boolean offer(E e) 取队首元素并删除 E remove() E poll() 取队首元素但不删除 E element() E peek() 使用 remove()之类的操作需要编写 try语句,而 poll()则需要编写if语句。
-
PriorityQueue
- 对PriorityQueue类每次调用remove()或者poll()方法总是返回优先级最高的元素。
- 放入PriorityQueue的元素,必须实现Comparable接口。例如我们存放String类型的元素,不管当初我是怎么放进去的,到最后弹出的时候只按照Comparable中定义的规则(这里是字母表的顺序)输出。(这点需要十分的重要)
- 如果不实现Comparable接口,则要编写Comparator(比较器)。
PriorityQueue<String> queue = new PriorityQueue<>(); queue.offer("C"); queue.offer("B"); queue.offer("A"); System.out.print(queue.poll() + queue.poll() + queue.poll()); // 输出:ABC
-
Deque
- Deque也是一个接口,并不能直接使用。
- 相应的实现类有==
ArrayDeque
和LinkedList
==。 - Deque是双端队列,允许两头都进,两头都出(Queue只允许单头进出)。
- 没有优先队列的优先级概念。
- 实际上扩展自Queu,但是使用Deque最好不要调用
offer()
,而是调用offerLast()
。
-
LinkedList全能选手,既可以作链表List,也可以作Queue、Deque、Stack。
-
Stack
- 栈只有入栈和出栈两种操作。
- 压栈:
push(E)
; - 出栈 + 删除:
pop()
; - 出栈 + 不删除:
peek()
。
- 压栈:
- 栈有容量限制,超出将触发StackOverflowError(栈溢出)异常。
- 栈可以用来进行进制之间的转换。
- 计算机在执行表达式的时候,并不是直接计算中缀表达式(例如 1 + 2 +3),而是把中缀表达式转为后缀表达式之后才开始计算(例如:123++),用到了栈。
- 栈只有入栈和出栈两种操作。
六、Iterator
-
Java的集合类都可以使用for each循环。
-
List
、Set
和Queue
会迭代每个元素,Map
会迭代每个key。 -
forEach循环和iterator是同源的:
- 编译前
List<String> list = List.of("Apple", "Orange", "Pear"); for (String s : list) { System.out.println(s); }
- 编译后
List<String> list = List.of("Apple", "Orange", "Pear"); for (Iterator<String> it = list.iterator(); it.hasNext(); ) { String s = it.next(); System.out.println(s); }
-
自定义iterator迭代器
// 总是倒序输出 class ReverseIterator implements Iterator<T> { int index; ReverseIterator(int index) { this.index = index; } @Override public boolean hasNext() { return index > 0; } @Override public T next() { index--; return ReverseList.this.list.get(index); } }
七、Collections
-
注意是Collections,而不是Collection。
-
JDK提供的工具类
-
常用方法
-
排序:Collections.sort(list);
-
洗牌:Collections.shuffle(list);
-
封装成不可变集合:Collections.unmodifiableList/Map/Set(mutable);
但是,继续对原始的可变List进行增删是可以的,并且,会直接影响到封装后的“不可变”List。所以在转换过后,我们最好立刻扔掉原始的List引用(赋值为 null )。
-
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/10500.html