thinking in java 第6天

第十一章:持有对象(容器类源码非常清楚也很强大,像我们这种菜鸟应该多学习)

  1. 泛型和集合类型安全
    • 向上转型可以适用
  2. 容器类:
    • Collection:一个独立元素的序列,这些元素都服从一条或者多条规则
      • list:按照插入的顺序保存元素,不关心是否重复
      • set:不能有重复元素
      • Queue:按照队列规则来确定对象产生的顺序
    • Map:键值对
  3. Arrays.asList():将一个数组当作list,但是底层然是以数组来实现的,所以当对这个List做增删操作时有可能引起改变数组大小
  4. 显示类型参数声明:List<T> t = Arrays.<T>asList();底层返回的是一个内部类ArrayList
  5. 容器的打印:
    • Collection打印出来的是方括号括住,每个逗号分隔的
    • Map则用大括号,键与值则是用等号联系
    • ArrayList和LinkedList都是List类型,都是按照被插入的顺序保存元素
    • HashSet,TreeSet,LinkedHashSet都是Set类型,是去重复的
      • hashSet的存储顺序非常复杂,待后面说
      • TreeSet:按照比较结果的升序存储对象
      • LinkedHashSet:按照添加的顺序保存对象
    • HashMap,TreeMap,LinkedHashMap,存储的顺序和上面一致,其实Set底层就是基于Map来实现的,后面会细说
  6. List:将元素维护在特定的序列中,在Collection的接口上添加了大量方法
    • ArrayList:易于随机访问,毕竟是依赖数组实现的
      • subList():这个函数所产生的列表的幕后就是初始列表,所以对返回的列表的操作会反映到初始列表中
      • 像remove(),retainAll()[表示取交集]等函数背后比对使用的都是equals函数,要注意这个函数比对的是引用,除非覆写,比如String类中
    • LinkedList:易于插入删除,是依赖链表实现的,这个类中多了很多函数,是为了实现栈和队列提供基础的
      • 双向链表实现
      • 是无头节点的双向链表
      • Queue实在LinkedList基础之上添加了element()/offer()/peek()/poll()/remove()等方法实现的
      • element()/getFirst()/peek()都是取第一个对象,但是前两者在list为空时抛出NoSuchElementException异常,peek则返回null
      • remove/removeFirst/pull()和上面类似,不过都是取移除并返回头
      • add/addFirst()/addLast()
  7. 迭代器
    • Iterator:单向的
      • 使用方法iterator()要求容器返回一个Iterator,Iterator将准备好返回序列的第一个元素
      • 使用next()获得序列的下一个元素
      • 使用hasNext()检查序列中是否有元素
      • 使用remove将迭代器新近返回的元素删除(一般要先调用next(),保证有新近返回的元素,因为根据源码知道,remove里删除的index是在next()方法里设置的)
    • ListIterator:只能用于List类的访问,而且是双向的
      • 可以通过调用listIterator()方法产生一个指向List开始处的ListIterator,并且还可以通过调用listIterator(n)创建一个一开始就指向列表索引为n的元素的ListIterator
      • 通过源代码知道ListIterator是对Iterator的一次扩展,增加了实现双向移动的一些函数
    • 依赖LinkedList实现栈,类名后面的<T>告诉编译器这将是一个参数化类型
    • import java.util.LinkedList;
      
      public class StackByLinkedList<T> {
      	private LinkedList<T> storage =  new LinkedList<T>();
      	public void push(T v){ storage.push(v); }
      	public T peek(){ return storage.peek(); }
      	public T pop(){ return storage.pop(); }
      	public boolean empty(){ return storage.isEmpty(); }
      	public String toString(){ return storage.toString(); }
      }
    • 当然在util包中实现了Stack这个类,不过是继承了Vector,依赖数组实现的
  8. Set:之前说过Set是依赖Map的key来实现的,可以看源码
    • 不保存重复的元素,一般利用这个特性来测试归属行
    • Set和Collection完全一样的接口,没有任何额外的功能
    • HashSet/TreeSet/LinkedHashSet
      • TreeSet依赖红黑树,结果是排序的
      • HashSet依赖散列函数
      • LinkedHashSet也使用了散列函数,但是使用了链表来维护元素的插入顺序
  9. Map:键值对,可以用于组合别的数据结构,如Map<A,List<? extends B>>();
  10. Queue:典型的FIFO
    • LinkedLIst提供了方法支持队列的行为,而且实现了Queue的接口
    • offer():将一个元素插入到队尾
    • peek/element都是在不移除的情况下返回对头
    • poll/remove都是在移除的情况下返回对头
    • PriorityQueue
      • 一般情况下会维持一个堆,在offer()插入时会根据一定的规则排序,可以通过Comparator来修改排序规则
      • 一般情况下重复是允许的,而且最小的值拥有最高的优先级
  11. Collection与iterator
  12. Foreach与迭代器
    • foreach适用于所有Collection
    • 所有实现了Iterable的接口都可以用foreach实现移动
    • public class IterableClass implements Iterable<String>{
      	private String[] words = {"s0","s1","s2","s3","s4"};
      	
      	public Iterator<String> iterator(){
      		return new Iterator<String>() {
      			private int index = 0;
      			public String next(){
      				return words[index++];
      			}
      			public boolean hasNext(){
      				return index < words.length;
      			}
      			public void remove(){
      				
      			}
      		};
      	}
      	
      	@Test
      	public void test(){
      		for(String s : new IterableClass()){
      			System.out.println(s+" ");
      		}
      	}
      	
      }
      


    • 所有的Collection(除了Map)都实现了Iterable接口,map可以使用Entry来构建成Set集合
    • import java.util.Map;
      
      import org.junit.Test;
      
      public class EnviromentVariables {
      	@Test
      	public void test(){
      //		System.getenv()
      		for(Map.Entry entry : System.getenv().entrySet()){
      			System.out.println(entry.getKey()+" : "+entry.getValue());
      		}
      	}
      }
    • 不存在任何数组到Iterable的自动转换,必须手工转换
    • Arrays.asList()产生的List对象会使用底层数组作为其物理实现,所以修改这个返回的List会修改底层的数组,如果不希望修改,则需要创建一个副本,如用new ArrayList<>包装一下创建一个引用副本

容器图


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值