JAVA编程思想学习笔记(十一)容器类

容器类

在《java编程思想》一书中,容器类本是在持有对象那一章节里面的,这里我特意给提出来了,因为内容代码比较多,与其放一起显得太臃肿,倒不如这样来的清爽些。

List

List承诺可以将元素维护在特定的序列中,List接口在Collection的基础上添加了大量的方法,使得可以在List中插入和移除元素。
有两种类型的List:

  • 基本的ArrayList,它擅长于随机访问元素,但是在中间插入和移除元素时比较慢。
  • LinkedList,它通过代价比较低的在List中间进行插入和删除操作,提供了优化的顺序访问。但是它在随机访问方面比较差。
    下面先介绍
    ArrayList
    对于ArrayList的方法可以先看下代码:
class Word{
	String w;
	Word(String w){
		this.w=w;
	}
	public String toString(){
		return w;
	}
}
class WordD extends Word{ 
	WordD(String w) {
		super(w);
		// TODO Auto-generated constructor stub
	}
	
	public String toString(){
		return w+"D";
		
	}
	
}
public class ListTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Word> ws = new ArrayList<Word>();
		Word a = new Word("A");
		Word b = new Word("B");
		Word c = new Word("C");
		Word d = new WordD("D");
		Word e = new Word("E");
		//增
		ws.add(a);
		ws.add(b);
		ws.add(c);
		ws.add(d);
		System.out.println("1:"+ws);
		//删
		System.out.println("2:"+"e:"+ws.remove(e)+"  b:"+ws.remove(b));
		System.out.println("3:"+ws);
		
		//插
		ws.add(2, e);
		System.out.println("4:"+ws);
		//查		
		System.out.println("5:"+ws.get(0)+":"+ws.indexOf(ws.get(0)));
		//截取
		List<Word> sub = ws.subList(1, 3);
		System.out.println("6:"+sub);
		System.out.println("7:"+ws.containsAll(sub));
		//清空
		ws.clear();
		System.out.println("8:"+ws);
	}

}

运行结果:

1:[A, B, C, DD]
2:e:false  b:true
3:[A, C, DD]
4:[A, C, E, DD]
5:A:0
6:[C, E]
7:true
8:[]

看了代码应该对ArrayList有一个大致的了解,下面仔细说下:

  • add方法:在list中添加对象,可以是子类的对象。可以在参数中设置添加的位置,作为插入来使用。
  • remove方法:将要移除的对象的引用传递给remove方法,就可以在List中移除该对象。删除成功返回true,要是想删除的对象不在List中,则返回false。
  • get方法:根据索引获得对应的在List中的对象。
  • indexOf方法:获得对象在List中的索引位置。
  • sublist方法:在List中截取一段,有两个参数,一个起始位置的索引,另一个是结束位置的索引,需要注意的是,截取出来的内容包括起始位置,但是不包括结束位置。
  • clear方法,清空List。

常用的方法基本就这些,还有一些其他的方法,在了解基本的这些后,也很容易看出来怎么用,比如addAll方法,显然就是add方法的变形,参数为一组对象就可以了。
接下来介绍
LinkedList
LinkedList也像ArrayList一样实现了基本的List接口,但是它执行某些操作时比ArrayList更高效,但是在随机访问方面更逊一筹。
Linked还添加了可以使其用作栈、队列或双端队列的方法。
这些方法中有些彼此之间只是名称的差异,或者存在些许差异。例如,getFirst和element完全一样,都是返回表头,而不移除它,如果为空,则跑出异常,而peek只是稍有差异,为空时返回null。
下面展示各方法的差异性:

class Word{
	String w;
	Word(String w){
		this.w=w;
	}
	public String toString(){
		return w;
	}
}
class WordD extends Word{ 
	WordD(String w) {
		super(w);
		// TODO Auto-generated constructor stub
	}
	
	public String toString(){
		return w+"D";
		
	}
	
}
public class ListTest {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		LinkedList<Word> ws = new LinkedList<Word>();
		Word a = new Word("A");
		Word b = new Word("B");
		Word c = new Word("C");
		Word d = new WordD("D");
		Word e = new Word("E");
		ws.add(a);
		ws.add(b);
		ws.add(c);
		ws.add(d);
		System.out.println("getFirst:"+ws.getFirst());
		System.out.println("element:"+ws.element());
		System.out.println("peek:"+ws.peek());
		
		System.out.println("remove:"+ws.remove());
		System.out.println("removeFirst:"+ws.removeFirst());
		System.out.println("poll:"+ws.poll());
		System.out.println("ws:"+ws);
		
		ws.addFirst(e);
		System.out.println("addFirst:"+ws);
		ws.offer(a);
		System.out.println("offer:"+ws);
		
		ws.add(c);
		System.out.println("add:"+ws);
		
	}

}

输出结果:

getFirst:A
element:A
peek:A
remove:A
removeFirst:B
poll:C
ws:[DD]
addFirst:[E, DD]
offer:[E, DD, A]
add:[E, DD, A, C]

后注,本来打算每个容器类都弄新弄一个章节,但是感觉后面的好多东西和前面的有重叠,还是放在一起好了。

Stack

Stack也就是栈,对于有一定基础的人应该不陌生,它秉持的是后进先出(LIFO)原则。
Stack有两个基本操作,入栈push,出栈pop,peek获得栈首但是不出栈,你会发现,这几个方法在LInkedList中都有,因此可以直接将LinkedList作为栈使用,不过,有时候为了让代码更加的清晰,我们还是会使用Stack。
下面是个简单的小例子:

public class StackTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Stack<String>stack=new Stack<String>();
		for(String s: "A B C D E F G".split(" ")){
			stack.push(s);
		}
		while(!stack.isEmpty()){
			System.out.println(stack.pop());
		}
	}

}

输出为:

G
F
E
D
C
B
A

Set

Set不保存重复的元素,set中最常被使用的是测试归属性,你可以轻而易举的询问某个对象是否在Set中,正因如此,查找就成为了Set中最重要的操作了。
Set具有与Collection完全一样的接口,实际上Set就是Collection,只是行为不同。(这是继承和多态思想的典型应用:表现不同的行为)。
下面使用HashSet做一个简单的实例:

public class SetTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Random rand = new Random(47);
		Set<Integer> set = new HashSet<Integer>();
		for(int i=0;i<30;i++){
			set.add(rand.nextInt(30));
		}
		System.out.println(set);
		
	}

}

输出结果为:

[0, 1, 2, 3, 5, 7, 8, 10, 11, 12, 13, 14, 16, 18, 19, 20, 21, 25, 26, 28, 29]

可以看出来重复的是不会出现的,但是感觉出来的结果像是有序的,这样想就错了,我们改下随机的范围,就可以看出来:

public class SetTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Random rand = new Random(47);
		Set<Integer> set = new HashSet<Integer>();
		for(int i=0;i<30;i++){
			set.add(rand.nextInt(500));
		}
		System.out.println(set);
		
	}

}

其结果是:

[128, 193, 258, 322, 200, 11, 75, 140, 204, 461, 206, 207, 20, 22, 278, 342, 89, 410, 288, 416, 361, 429, 368, 498, 51, 309, 55, 383]

因为出于速度的考虑,HashSet使用了散列,散列在后面再介绍。HashSet所维护的顺序与TreeSet和LinkedHashSet都不同因为它们的实现具有不同的元素存储方式。TreeSet将元素存储在红黑树数据结构中,所以,想对结果排序,可以使用TreeSet。
下面就要介绍set最重要的用法,测试归属性,同样,我写了个例子,因为通过代码更加直观。

public class SetTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Random rand = new Random(47);
		Set<String> set = new HashSet<String>();
		Collections.addAll(set, "A B C D E F G".split(" "));
		System.out.println("A:"+set.contains("A"));//包含
		System.out.println("H:"+set.contains("H"));//不包含
		Set<String> set2 = new HashSet<String>();
		Collections.addAll(set2, "E F G".split(" "));
		System.out.println("set2:"+set.contains(set2));//普通包含
		System.out.println("set2:"+set.containsAll(set2));//包含全部
		set.remove("E");
		System.out.println("set2:"+set.containsAll(set2));//部分不一样
		set.removeAll(set2);
		System.out.println("set:"+set);
	}

}

其结果如下:

A:true
H:false
set2:false
set2:true
set2:false
set:[A, B, C, D]

Map

Map用来存储键值对,也就是给一个“键”就可以获得对应的“值”。键值对可以很方便的取出想要的对象,下面就是一个例子,取出来对象,统计数量:

public class MapTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Map<String,Integer> m = new HashMap<String,Integer>();
		for(String s:"hello word hello java".split(" ")){
			Integer i= m.get(s);
			m.put(s, i==null?1:i+1);
		}
		System.out.println(m);
	}

}

结果:

{java=1, hello=2, word=1}

同时map还可以和其他的容器结合使用:

public class MapTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Map<String,List<String>> m = new HashMap<String,List<String>>();
		m.put("A", Arrays.asList("Apple","Angle"));
		m.put("B", Arrays.asList("Baby","Banana"));
		m.put("C", Arrays.asList("Come","Candy","China"));

		System.out.println(m);
		System.out.println(m.get("A"));
		System.out.println(m.get("A").get(1));
	}

}

输出:

{A=[Apple, Angle], B=[Baby, Banana], C=[Come, Candy, China]}
[Apple, Angle]
Angle

Queue

Queue队列,按照先进先出原则存储数据,这个和栈Stack基本一样,都是通过LInkedList向上转型成Queue。下面一个简单的例子,便于理解:


    public class QueueTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Queue<Integer> q= new LinkedList<Integer>();
		for(int i = 0 ; i < 10 ; i++){
			q.offer(i);
		}
		System.out.println(q);
		System.out.println(q.poll());
	}

}

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值