通过学习《Java编程思想》,并结合其他资料,复习巩固Java知识。欢迎指正错漏。
准备算法刷题,所以第一篇读书笔记的关注重点:
容器(第11、17章),字符串(第13章),数组(第16章)
容器 Container/集合 Collection

Collection
List:
有序,可重复,按插入顺序保存
常用实现类:
ArrayList:基于动态数组,随机访问快
LinkedList:基于双向链表,中间插入、移除元素快
List<T> list = new ArrayList<>()
T必须是Object,基础类型如int就不行。
注:List是接口(interface),ArrayList是实现(implementation)。
ArrayList类继承并实现了List接口,是向上转型。
A a = new B();
向上转型,通俗点就是说先创建一个子类对象B,然后把它强制转型为A类对象。
a会有A类所有属性和方法,若子类B有重复的属性(如int i)和方法(如void f()),
a会采用A类的属性和B类的方法,子类B中独有的方法被忽略。
为什么用 List<> list = new ArrayList<>() ,
而不用 ArrayList<> alist = new ArrayList<>()呢?
因为List接口有多个实现类,也许哪一天你需要换成别的实现类如 LinkedList,
这时你只要改这一行就行了: List<> list = new LinkedList<>();
其它使用了list的代码根本不需要改动。
遍历方式:for循环,Iterator。(推荐foreach)
// 方法1
Iterator it1 = list.iterator();
while(it1.hasNext()){
System.out.println(it1.next());
}
// 方法2
for(Iterator it2 = list.iterator(); it2.hasNext();){
System.out.println(it2.next());
}
// 其他:foreach,for + get()
如果要遍历删除某元素:
// 方法1:使用for循环倒序(删除元素后动态数组下标会变动)
for (int i = list.size() - 1; i >= 0; i--) {
String s = list.get(i);
if (s.equals("b")) {
list.remove(s);
}
}
// 方法2:使用Iterator的remove
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.equals("b")) {
it.remove();
}
}
-
Queue 队列(FIFO) 一端插入,一端移除。并发常用。
Queue<> q = new LinkedList<>()
-
Stack 叠加栈(LIFO)直接用
LinkedList<> s = new LinkedList<>()
-
PriorityQueue 优先队列(FIFO)自然顺序,可设比较器Comparator,元素不许为null。保证每次取出的元素是队列中权值最小的。
PriorityQueue<> p = new PriorityQueue<>()
应用例子 -
Deque (double-ended queue) 双向队列。应该自己创建一个类,用 LinkedList实现有关方法。
Set :
没有重复元素
常用实现类:
HashSet:快速查找和添加,基于散列函数,无序输出。是最常用的。
Set<> s = new HashSet<>()
LinkedHashSet: 快速查找,基于散列函数,插入顺序保存元素
TreeSet: 自然排序/自定义排序,基于红黑树排序。迭代快
遍历方式:Iterator
Map 映射表,键值对
常用实现类:
HashMap: 快速查找和添加,基于散列。是最常用的。
Map<K, V> map = new HashMap<>()
HashMap线程不安全,允许null作为key和Value。创建时完成这一操作,可防止意外的非同步访问:Map map = Collections.synchronizedMap(new HashMap(...));
LinkedHashMap: 插入顺序保存元素,快速访问,基于散列
TreeSet: 保持键的有序,基于红黑树
散列码 hash code:相对唯一,代表对象的int值。通过将该对象的某些信息进行转换而生成。散列是映射中存储元素的最常用方式,查询效率高。
已弃用:Vector, Enumeration接口, Hashtable, Stack, BitSet
字符串
String对象是不可变的,修改String值的方法实际是创建全新的String对象。StringBuilder,StringBuffer可变。
执行速度:StringBuilder > StringBuffer > String
StringBuilder:线程非安全,不支持并发。大部分情况下可使用。
StringBuffer:线程安全,支持并发。
format() 和 printf() 完全等价。
Formatter:用于格式化输出
StringTokenizer:使用分隔符,分解字符串
indexOf():得到对象内第一次出现子字符串的位置,可设置startIndex
charAt() :根据下标字符串中提取特定字符。
str.charAt(0):提取str中的第一个字符,str.charAt(str.length()-1) 提取最后一个字符。
substring() :字符串中提取特定位置的一段子字符串。
正则表达式:Java里是 \\d, 其他语言 \d
Java8 新方法:
String.join():拼接字符串并且使用分隔符,与split()功能相反。
String s = String.join("/","aa”,"bb”,"cc”);
等效于:String s = “/"+”aa”+“/"+"bb”“/"+"cc”;
String b = String.join(", ", ZoneId.getAvailableZoneIds());
数组
数组效率比容器高,大小固定。
Arrays.fill()为数组填充单一值,可设置起止位置。
数组转为List:List<String> list = Arrays.asList(arr);
List转为数组:String[] arr = (String[])list.toArray(new String[list.size()]);
System.arraycopy():复制数组,比用for循环快
Arrays.equals(arr1, arr2):比较两个数组
Arrays.sort(arr):排序。
Arrays.sort(arr, String.CASE_INSENSITIVE_ORDER); 忽略大小写排序
Arrays.binarySearch(arr, e):在已排序的数组中查找元素。有重复元素则无法保证找到的是哪一个。
References:
《Java编程思想》思维导图
吕龙宝的《Java编程思想》学习笔记
List和ArrayList的区别
常用JAVA集合
ArrayList遍历删除元素的常见陷阱
对Java向上转型的理解
写给大忙人看的Java SE 8
网友评论