1. 容器类被分为两类:Collection和Map

  • Collection是一个接口:包括:

    • List接口:

      • ArrayList:按照被插入顺序保存元素, 查询快, 增删改慢
      • LinkedList:按照被插入顺序保存元素, 增删改块,查询慢。
    • Set接口:元素不能重复
      • HashSet:已相当复杂的方式来存储元素,这种技术是最快的获取元素的方式
      • TreeSet:按照结果的升序保存元素
        • 可以自行执行排序方式。默认是按照字典顺序排序。如果想按照字母顺序排序,可以向TreeSet构造器中传入String。CASE_INSENTIVE_ORDER.
      • LinkedHashSet:按照添加顺序保存元素
    • Queue接口
  • 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));
      }
    • 容器的打印, 直接打印容器名, 无需任何帮助.

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编程思想第四版第十一章总结的更多相关文章

  1. java编程思想第四版第十一章习题

    第一题 package net.mindview.holding.test1; import java.util.ArrayList; import java.util.List; /** * 沙鼠 ...

  2. java编程思想第四版第十三章字符串 习题

    fas 第二题 package net.mindview.strings; import java.util.ArrayList; import java.util.List; /** * 无限循环 ...

  3. Java编程思想第四版*第七章*个人练习

    欢迎加群:239063848 成团的笔记:该组仅用于技术共享和交流,问题和答案公布 潘基聊天.禁止广告.禁止招聘-- 练习1:(2)创建一个简单的类.第二个类中,将一个引用定义为第一个类的对象.运用惰 ...

  4. java编程思想第四版第六章习题

    (略) (略) 创建两个包:debug和debugoff,他们都包含一个相同的类,该类有一个debug()方法,第一个版本显示发送给控制台的String参数,而第二版本什么也不做,使用静态import ...

  5. java编程思想第四版第六章总结

    1. 代码重构 为什么f要代码重构 第一次代码不一定是完美的, 总会发现更优雅的写法. 代码重构需要考虑的问题 类库的修改不会破坏客户端程序员的代码. 源程序方便扩展和优化 2. 包 创建一个独一无二 ...

  6. java编程思想第四版第五章习题

    创建一个类, 它包含一个未初始化的String引用.验证该引用被Java初始化成了null package net.mindview.initialization; public class Test ...

  7. java编程思想 第四版 第六章 个人练习

    欢迎加群:239063848 进群须知:本群仅用于技术分享与交流.问题公布与解答 禁止闲聊.非诚勿扰 练习1:(1)在某个包中创建一个类,在这个类所处的包的外部创建该类的一个实例. import mi ...

  8. java编程思想第四版第十三章字符串 总结

    1. String和StringBulider的使用 通过书中介绍, 我们得知如下结论: 当使用+连接符将字符串进行拼接的时候, 编译器会进行自动优化为使用StringBuilder连接字符串. 当在 ...

  9. java编程思想第四版第七章习题

    (略) (略) (略) (略) 创建两个带有默认构造器(空参数列表)的类A和类B.从A中继承产生一个名为C的新,并在C内创建一个B类的成员.不要给C编写构造器.创建一个C类的对象并观察其结果. pac ...

随机推荐

  1. RIDE的External Resources

    External Resources(外部资源):主要指不在project管辖范围内的资源文件. 通俗来说,如果是目录的project,只要不在自己目录范围内的资源文件都算外部资源:如果是文件的pro ...

  2. python编程系列---白痴女朋友(我没有女朋友!)看了都能懂的TCP/IP协议介绍

    前言 早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Microsoft都有各自的网络协议,互不兼容:为了把全世界的所有不同类型的计算机都连接起来,就必须规定一套全球通用的协议,为 ...

  3. Spring Boot 2.X(十一):全局异常处理

    前言 在 Java Web 系统开发中,不管是 Controller 层.Service 层还是 Dao 层,都有可能抛出异常.如果在每个方法中加上各种 try catch 的异常处理代码,那样会使代 ...

  4. Spring Cloud ---- 服务消费与负载均衡(feign)

    feign是一个声明式的伪客户端,只需要创建一个接口并且注解,它具有可插拔的特性.feign集合了Ribbon,再与Eurake结合实现服务的注册发现与负载均衡.结合Hystrix,具有熔断功能. 1 ...

  5. angularjs通过ng-bind-html指令和$sce服务绑定html

    代码: <!doctype html> <html lang="en"> <head> <meta charset="UTF-8 ...

  6. C语言中的isalpha,isdigit,islower,isupper等一系列函数

    TITLE:c语言中的isalpha,isdigit,islower,isupper等一系列函数 已经全部验证检查,无任何错误 isalnum(测试字符是否为英文或数字) 相关函数 isalpha,i ...

  7. 详细解读 Spring AOP 面向切面编程(二)

    本文是<详细解读 Spring AOP 面向切面编程(一)>的续集. 在上篇中,我们从写死代码,到使用代理:从编程式 Spring AOP 到声明式 Spring AOP.一切都朝着简单实 ...

  8. (一)初识EasyTouch

    Easy Touch是一个手指触控(可以鼠标)的插件,可以非常方便的实现各种功能,使用插件第一步是添加Easy Touch组件,可以右键添加也可以在一个空的游戏物体上添加Easy Touch脚本(非事 ...

  9. 使用 Nginx 搭建静态资源 web 服务器

    在搭建网站的时候,往往会加载很多的图片,如果都从 Tomcat 服务器来获取静态资源,这样会增加服务器的负载,使得服务器运行 速度非常慢,这时可以使用 Nginx 服务器来加载这些静态资源,这样就可以 ...

  10. 第一篇 Flask初识

    一. Python 现阶段三大主流Web框架 Django Tornado Flask 对比 1.Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, 不 ...