java编程思想第四版第十一章总结
1. 容器类被分为两类:Collection和Map
- Collection是一个接口:包括:
- List接口:
- ArrayList:按照被插入顺序保存元素, 查询快, 增删改慢
- LinkedList:按照被插入顺序保存元素, 增删改块,查询慢。
- Set接口:元素不能重复
- HashSet:已相当复杂的方式来存储元素,这种技术是最快的获取元素的方式
- TreeSet:按照结果的升序保存元素
- 可以自行执行排序方式。默认是按照字典顺序排序。如果想按照字母顺序排序,可以向TreeSet构造器中传入String。CASE_INSENTIVE_ORDER.
- LinkedHashSet:按照添加顺序保存元素
- Queue接口
- List接口:
- Map接口
- HashMap:已相当复杂的方式来存储元素(散列函数),这种技术是最快的获取元素的方式
- TreeMap:按照比较结果的升序保存,元素存储在红黑树数据结构。
- LinkedHashMap:按照添加顺序保存元素。
2. 定义集合的时候,使用向上转型,是一个好的习惯
List<Apple> list = new ArrayList<Apple>();
注意:ArrayList已经被向上转型为List,这样做的好处是,如果你想使用其他List的实现类也是可以的。缺点是,在ArrayList中有一些额外的方法,不包含在List中,如果需要调用这些方法,还需要使用ArrayList来定义。
3. Collection集合的使用
- 添加一组元素
package net.mindview.holding; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List; public class AddingGroups { public static void main(String[] args) {
//1. Collection集合,有一个构造方法, 可以接受一个集合作为参数, 将数组内容直接作为Collections的内容. Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(,,,,));
Integer[] moreInts = {, , , , };
//2. 集合有一种方法,添加一个数组为它的元素. 这种方法没有Collections.addAll高效
//原因: 第一种方式首先要初始化,然后将数组转换为集合后, 赋值. 第二种方法方法直接赋值,所以更高效
collection.addAll(Arrays.asList(moreInts)); //定义一个集合, 使用Collections.addAll()方式添加元素是一种推荐的方式.效率高
Collections.addAll(collection, ,,,,);
Collections.addAll(collection, moreInts); //将数组直接转换为list,有两点需要说明:1. 大小固定, 不能添加元素,删除元素, 可以修改. 2. 局限性,下面的代码说明.
List<Integer> list = Arrays.asList(,,,,);
list.set(, );
}
}相信看上面的注释, 下面说一说Arrays.asList()的局限性.
package net.mindview.holding; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; /**
* 这里说的是一个间接继承和直接继承的问题
*/
class Snow {}
class Powder extends Snow{}
class Light extends Powder{}
class Heavy extends Powder{}
class Crusty extends Snow{}
class Slush extends Snow{}
public class AsListInference { public static void main(String[] args) {
//1. 下面的定义可以通过, 他们都继承自Snow
List<Snow> snow1 = Arrays.asList(new Powder(), new Crusty(), new Slush()); //2. 下面的定义不能通过, 因为他们都是间接继承自snow.而非直接
//List<Snow> snow2 = Arrays.asList(new Light(), new Heavy()); //3. 上面的方式编译不通过,但是下面的却可以.为什么呢? 因为他从第一个元素了解到了此目标类型是snow
List<Snow> snow3 = new ArrayList<Snow>();
Collections.addAll(snow3, new Light(), new Heavy()); //4. 方法2可以通过显示类型参数说明,来明确指出转换的类型
List<Snow> snow4 = Arrays.<Snow>asList(new Light(), new Heavy());
} } - 容器的打印
- 数组的打印,使用Arrays.toString(数组名);
public static void main(String[] args) {
String[] str = new String[];
System.out.println(str);
System.out.println(Arrays.toString(str));
} - 容器的打印, 直接打印容器名, 无需任何帮助.
- 数组的打印,使用Arrays.toString(数组名);
4. Stack
栈: 先进后出(LIFO),有时栈也被称为叠加栈, 因为最后“压入”的,最先弹出。
LinkedList具有能够直接实现栈的所有功能的方法。因此可以直接将LinkedList作为栈直接使用。
也就是说LinkedList中有方法是先进后出的。
package net.mindview.holding; import java.util.LinkedList; /**
* 模拟栈
*/
public class Stack<T> {
private LinkedList<T> storage = new LinkedList<T>(); //进入
public void push(T v){
storage.addFirst(v);
} public T peek(){
return storage.removeFirst();
} //取出
public T pool(){
return storage.removeFirst();
} public boolean empty(){
return storage.isEmpty();
} public String toString(){
return storage.toString();
} }
package net.mindview.holding; public class StackTest { public static void main(String[] args) {
Stack<String> stack = new Stack<String>();
for(String s:"this is my dog!".split(" ")){
stack.push(s);
} if(!stack.empty()){
System.out.println(stack.peek());
System.out.println(stack.pop()+" ");
System.out.println(stack.pop()+" ");
System.out.println(stack.peek());
}
}
}
运行结果:
dog!
dog!
my
is
通过这个案例: 可以看出, 所谓的先进后出,指的是, add最后进来的, remove时最先出去. 跟排序没有任何关系.
5. Queue 队列
队列是一个典型的先进先出的容器. 即从容器的一段放入,从另一端取出. 并且事物放入容器的顺序与取出的顺序是相同的。
LinkedList提供了方法以支持队列的行为。并且它实现了Queue接口。因此LinkedList可以用作Queue的一种实现。通过将LinkedList向上转型为Queue,下面展示了Queue的用法。
package net.mindview.holding; import java.util.LinkedList;
import java.util.Queue;
import java.util.Random; public class QueueDemo { public static void print(Queue queue){
//从队列中取元素--先放进去的,先取出来
while(queue.peek() != null){
//从队列中删除一个元素
System.out.print(queue.remove() + " ");
}
System.out.println();
}
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<Integer>();
Random rand = new Random();
for(int i=; i<; i++){
//向队列里放入元素
queue.offer(rand.nextInt(i+));
}
print(queue); Queue<Character> qc = new LinkedList<Character>();
for(char c:"Brontosaurus".toCharArray()){
//向队列里放入元素
qc.offer(c);
}
print(qc);
}
}
B r o n t o s a u r u s
- offer()方法,:在允许的情况下,将一个元素插入到队尾。或者返回false。
- peek()和element():在不移除的情况下返回对头。但是peek方法在队列为空时,返回null。而element()会抛出NoSuchElementException异常。
- poll()和remove():将移除并返回队头。poll在队列为空时返回null,remove在队列为空是抛出NoSuchElementException异常。
这里想Queue中放入元素使用的时offer,取出元素使用的时peek,删除元素使用的remove。先放进去的先取出来。
我们再说到Stack时,看到LinkedList可以实现Stack先进后出。看到队列的Queue的时候, 又说LinkedList可以实现Queue先进先出。这是怎么回事呢?来看看API,原来是这么回事
6. PriorityQueue:优先级队列
优先级队列声明,下一个弹出元素是最需要的元素。也就是说是优先级最高的元素。当你使用offer方法来出入一个对象时,这个对象会在队列中被排序。默认的顺序将使用对象在队列中的自然顺序。但你也可以通过自己的Comparator来修改这个顺序。
PriorityQueue可以确保当你调用peek(), poll(), remove()方法时, 获取元素将是队列中优先级最高的元素.
package net.mindview.holding; import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.Set; public class PriorityQueueDemo { public static void main(String[] args) {
/*
* 对于数字而言, 最小的数字优先级最高
*/
PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();
Random rand = new Random();
for(int i=;i<;i++){
priorityQueue.offer(rand.nextInt(i+));
}
QueueDemo.print(priorityQueue);
/*
* 将一个list集合中的元素放入队列
* 并且使用自定的排序方式排序
*/
List<Integer> ints = Arrays.asList(, , , , , , , , , ,
, , , , , , );
priorityQueue = new PriorityQueue<Integer>(ints);
QueueDemo.print(priorityQueue);
//提供了一个构造器, 使用自定义的排序方法.第二个参数是新的排序方法,继承了Comparator类.
priorityQueue = new PriorityQueue<Integer>(ints.size(), Collections.reverseOrder());
priorityQueue.addAll(ints);
QueueDemo.print(priorityQueue); /*
* 字符串集合放入到优先级队列
*/
String fact = "EDUCATION SHOULD ESCHEW OBFUSACTION";
List<String> strings = Arrays.asList(fact.split(" "));
PriorityQueue<String> stringPQ = new PriorityQueue<String>(strings);
QueueDemo.print(stringPQ); /*
* 使用set存储不重复的字符集合
* 最小的值有最高的优先级. 空格的优先级比字母高
*/
Set<Character> charSet = new HashSet<Character>();
for(char c: fact.toCharArray()){
charSet.add(c);
}
PriorityQueue<Character> charPQ = new PriorityQueue<Character>(charSet);
QueueDemo.print(charPQ);
}
}
运行结果:
EDUCATION ESCHEW OBFUSACTION SHOULD
A B C D E F H I L N O S T U W
1. 数字越小,优先级越高
2. 空格的优先级比字母高
3. 字符串,字符都可转换为对应的数字处理.
7. Iterator
java中, 用迭代器Iterator而不是集合Collection来表示集合间的共性。但是, 实现了Collection就意味着需要提供Iterator()方法。
(未完,待完善)
8. Foreach和迭代器
Iterable接口:该接口包含一个能够产生Iterator的iterator()方法,并且Iterable接口被foreach用来在序列中移动。因此,如果你创建的类实现了Iterable接口,都可以将它用于foreach语句中:
package net.mindview.holding; import java.util.Iterator; /**
* Iterable 接口包含一个能够产生Iterator的iterator()方法. 并且Iterable接口被用来在foreach用来在序列中移动。
* 因此,如果你创建了任何实现Iterable的类,都可以将其用于foreach语句中。
* @author samsung
*
*/
public class IterableClass implements Iterable<String>{
protected String[] words = ("And that is how we know the Earth to be banana-shaped.").split(" "); @Override
public Iterator<String> iterator() {
// TODO Auto-generated method stub
return new Iterator<String>(){
private int index = ; @Override
public boolean hasNext() {
return index < words.length;
} @Override
public String next() {
return words[index++];
} @Override
public void remove() {
throw new UnsupportedOperationException();
}
};
} public static void main(String[] args) {
//只要这个类实现了Iterable,就可以使用foreach语句遍历
for(String str: new IterableClass()){
System.out.println(str);
}
}
}
运行结果
And
that
is
how
we
know
the
Earth
to
be
banana-shaped.
9.适配器方法
我们知道一个类如果实现了Iterable接口, 他就要重写返回Iterator类型的iterator方法,我们使用的时候,就可以使用foreach的方式来遍历这个类。但是,这种实现接口的方式,只能够有一个种遍历方法。假如:我现在想要有多种遍历方案。比如:正序遍历,反序遍历,该如何实现呢?我们使用适配器方法来实现。代码如下:
package net.mindview.holding; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator; class ReversibleArrayList<T> extends ArrayList<T>{
private static final long serialVersionUID = 1L; public ReversibleArrayList(Collection<T> c) {
super(c);
} /**
* 实现了一个反转, 将传递过来的集合,反向输出
*/
public Iterable<T> reversed(){
return new Iterable<T>(){
@Override
public Iterator<T> iterator() {
return new Iterator<T>(){
int current = size()-; @Override
public boolean hasNext() {
return current >= ;
} @Override
public T next() {
return get(current--);
} @Override
public void remove() {
// TODO
}
};
}
};
}
} public class AdapterMethodIdiom { public static void main(String[] args) {
ReversibleArrayList<String> r = new ReversibleArrayList(Arrays.asList("To be or not to be".split(" ")));
for(String str: r){
System.out.print(str + " ");
}
System.out.println();
for(String str:r.reversed()){
System.out.print(str + " ");
}
} }
这个例子展示了, 我在一个类中,可以定义多种foreach循环的方式。下面我们使用这种方式,为IterableClass定义两种其他的循环方式:
package net.mindview.holding; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random; /**
* 继承了IterableClass类,就拥有了一种遍历方法了
* @author samsung
*
*/
public class MultiIteratorClass extends IterableClass{ /**
* 反序遍历
* @param args
*/
public Iterable<String> reverse(){
return new Iterable<String>(){
@Override
public Iterator<String> iterator() {
return new Iterator<String>(){
int count = words.length-;
@Override
public boolean hasNext() {
return count >= ;
} @Override
public String next() {
return words[count--];
} @Override
public void remove() {
}
};
}
};
} /**
* 随机访问遍历
* 这里没有创建自己的Iterator,而是直接返回被打乱的List中的Iterator.
* 这里使用Collections.shuffle()方法并没有影响到原来的数组,这是将原来数组的元素的引用打乱了.注意,是引用打乱了.
*
*/
public Iterable<String> randomized(){
return new Iterable<String>(){
@Override
public Iterator<String> iterator() {
List<String> shuffled = new ArrayList<String>(Arrays.asList(words));
Collections.shuffle(shuffled, new Random());
return shuffled.iterator();
} };
} public static void main(String[] args) {
MultiIteratorClass m = new MultiIteratorClass();
for(String s:m){
System.out.print(s+" ");
}
System.out.println();
for(String s: m.reverse()){
System.out.print(s+" ");
}
System.out.println();
for(String s: m.randomized()){
System.out.print(s+" ");
}
}
}
这里面在说说Collection.shuffle()方法. 看下面的例子就明白了
package net.mindview.holding; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random; public class ModifyingArraysAsList { public static void main(String[] args) {
Random rand = new Random();
Integer[] ia = {,,,,,,,,,};
/*
* list1包装了一层
* 从结果可以看出: 如果数组转List后被包装一层,调用Collections.shuffle打乱顺序,
* 打乱的是数组中元素的引用,数组的顺序没有改变
*/
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
System.out.println("Before shuffling:"+list1);
Collections.shuffle(list1, rand);
System.out.println("After shuffling: "+list1);
System.out.println("array: "+Arrays.toString(ia)); /*
* list2没有包装
* 从结果可以看出: 如果数组转List后没有包装,调用Collections.shuffle打乱顺序,打乱的是数组中元素的顺序
*/
List<Integer> list2 = Arrays.asList(ia);
System.out.println("Before shuffling:"+list2);
Collections.shuffle(list2, rand);
System.out.println("After shuffling: "+list2);
System.out.println("array: "+Arrays.toString(ia)); } }
java编程思想第四版第十一章总结的更多相关文章
- java编程思想第四版第十一章习题
第一题 package net.mindview.holding.test1; import java.util.ArrayList; import java.util.List; /** * 沙鼠 ...
- java编程思想第四版第十三章字符串 习题
fas 第二题 package net.mindview.strings; import java.util.ArrayList; import java.util.List; /** * 无限循环 ...
- Java编程思想第四版*第七章*个人练习
欢迎加群:239063848 成团的笔记:该组仅用于技术共享和交流,问题和答案公布 潘基聊天.禁止广告.禁止招聘-- 练习1:(2)创建一个简单的类.第二个类中,将一个引用定义为第一个类的对象.运用惰 ...
- java编程思想第四版第六章习题
(略) (略) 创建两个包:debug和debugoff,他们都包含一个相同的类,该类有一个debug()方法,第一个版本显示发送给控制台的String参数,而第二版本什么也不做,使用静态import ...
- java编程思想第四版第六章总结
1. 代码重构 为什么f要代码重构 第一次代码不一定是完美的, 总会发现更优雅的写法. 代码重构需要考虑的问题 类库的修改不会破坏客户端程序员的代码. 源程序方便扩展和优化 2. 包 创建一个独一无二 ...
- java编程思想第四版第五章习题
创建一个类, 它包含一个未初始化的String引用.验证该引用被Java初始化成了null package net.mindview.initialization; public class Test ...
- java编程思想 第四版 第六章 个人练习
欢迎加群:239063848 进群须知:本群仅用于技术分享与交流.问题公布与解答 禁止闲聊.非诚勿扰 练习1:(1)在某个包中创建一个类,在这个类所处的包的外部创建该类的一个实例. import mi ...
- java编程思想第四版第十三章字符串 总结
1. String和StringBulider的使用 通过书中介绍, 我们得知如下结论: 当使用+连接符将字符串进行拼接的时候, 编译器会进行自动优化为使用StringBuilder连接字符串. 当在 ...
- java编程思想第四版第七章习题
(略) (略) (略) (略) 创建两个带有默认构造器(空参数列表)的类A和类B.从A中继承产生一个名为C的新,并在C内创建一个B类的成员.不要给C编写构造器.创建一个C类的对象并观察其结果. pac ...
随机推荐
- prototype与 _proto__的关系
prototype与 __ proto__ 都是在这个过程中催生的产物,我们一会儿马上讨论,在这之...做对象即可,那javascript种究竟是通过什么来明确继承关系的呢. 一.构造函数: 构造函数 ...
- opencv::Sobel算子
卷积应用-图像边缘提取 卷积应用-图像边缘提取 边缘是什么 – 是像素值发生跃迁的地方,是图像的显著特征之一, 在图像特征提取.对象检测.模式识别等方面都有重要的作用. 如何捕捉/提取边缘 – 对图像 ...
- 《Java并发编程实战》读书笔记-第一部分 基础知识小结
并发技巧清单 可变状态是至关重要的 所有的并发问题都可以归结为如何协调对并发状态的访问.可变状态越少,就越容易确保线程安全性. 尽量将域声明为final类型,除非需要它们是可变的. 不可变对象一定是线 ...
- netty中Pipeline的ChannelHandler执行顺序案例详解
一.netty的Pipeline模型 netty的Pipeline模型用的是责任链设计模式,当boss线程监控到绑定端口上有accept事件,此时会为该socket连接实例化Pipeline,并将In ...
- CSP考场Emacs使用指南[原创]
前言: 据说,CSP考试,之后不再支持windows了呢. windows用户真得劲! 那用什么系统? Ubuntu上场了 Ubuntu编译指南 进入Ubuntu系统,在你想存的文件夹中新建一个空白文 ...
- Gstreamer基础教程10 - Streaming
摘要 我们把直接从网络播放一个媒体文件的方式称为在线播放(Online Streaming),我们已经在以往的例子中体验了GStreamer的在线播放功能,当我们指定播放URI为 http:// 时, ...
- Intellij IDEA 常用的插件 建议全装
介绍几个常用的插件 Alibaba Java Coding Guidelines https://plugins.jetbrains.com/plugin/10046-alibaba-java-cod ...
- 第3次作业-MOOC学习笔记:Python网络爬虫与信息提取
1.注册中国大学MOOC 2.选择北京理工大学嵩天老师的<Python网络爬虫与信息提取>MOOC课程 3.学习完成第0周至第4周的课程内容,并完成各周作业 4.提供图片或网站显示的学习进 ...
- 关于javascript闭包的最通俗易懂的理解
这两天在研究闭包,网上一通找,有牛人写的帖子,有普通人写的帖子,但是大多没戳中本小白所纠结的点,而且大多插入了立即执行函数,其实根本不需要的,反而让人产生了误解.这里我用我的方式讲解一下闭包. 1.目 ...
- vue cli3.3 以上版本配置vue.config.js
// vue.config.js 配置说明//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions// 这里只 ...