您的位置:首页 > 编程语言 > Java开发

java之 ------ 集合【详解】

2015-08-14 01:59 204 查看
集合

一、集合的概念

个人理解:说简单点就类似如,但又远厉害于数组。数组只能定长、类型单一,而集合则是在数组上面的扩充,放大。集合可以同时放多个类型对象,也就是人们说的元素,且数量可变的。

书面解释:集合是包含多个对象的简单对象,所包含的对象称为元素。集合里面可以包含任意多个对象,数量可以变化;同时对对象的类型也没有限制,也就是说集合里面的所有对象的类型可以相同,也可以不

同。集合:数量不限、类型不限;数组:定长、类型单一。

二、数据存储结构分类

主要就是看存储的方式,像数组就是顺序存储,而集合的存储方式就比较丰富。有:(1)顺序存储 (2)链式存储 (3)树形存储(4)散列存储Hash (5)Map映射存储

三、集合框架



(实现就是当前使用较多的(运用较多的就是这六中),历史集合类就是现在不常用的)

1、集合框架中各接口的特点

1)Collection接口

是一组允许重复的对象。

Collection接口用于表示任何对象或元素组。想要尽可能以常规方式处理一组元素时,就使用这一接口。

而且里面还用到了Iterator接口,也就是Iterator迭代器:主要用来枚举集合中的元素。(看例子就懂了,在杭电a过题的就容易理解点。跟Scanner相似。简单的可以理解为:将集合中所有的元素都放在迭代器中(一个特写的容器),然后遍历里面所有的内容)

实现类:LinkedList ArrayList

(至于内部的方法,直接看其实现类中的方法即可)

例:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

import cn.hncu.bean.Person;

public class CollectionDemo {

	public staticvoid main(String[] args) {
		//Collection col = new ArrayList();
		//Collection<Object> col = new ArrayList<Object>();//元素的存放顺序和添加是一致的
		Collection<Object> col = new HashSet<Object>();//元素的存放顺序由内部的Hash算法根据元素的值来决定,对于对象类型如Person对象,每次new时的地址是不一样的,因此每次运行结果中,它的顺序可能是变化的
		
		//增 add
		col.add(1); //从jdk1.5以后,可以自动包装
		col.add(3);
		col.add(2);
		col.add(new Person(25,"Jack"));
		col.add("Java");
		col.add(2);//添加重复的元素,对于List是可以的,而对于Set是加不进的。 
		
		//删 remove 移除的是元素本身
		//col.remove(3);//col.remove(2);
		
		//改
		//col.remove(1); col.add(4); //不合理,因为位置变了
		Object objs[] = col.toArray();
		col.clear();
		for(int i=0;i<objs.length;i++){
			if(objs[i].equals(1)){
				objs[i]=4;
			}
			col.add(objs[i]);
		}
		
		//查(遍历)
		//增强for循环(forEach语句),只能读全部,而且没有下标的概念
//		for(Object obj: col){
//			System.out.println(obj);
//		}
		//用迭代器Iterator来进行遍历集合
		Iterator<Object> it = col.iterator();
		while(it.hasNext()){
			Object obj = it.next();
			if(obj instanceof Person){
				System.out.println("Object:"+obj);
			}else if(obj instanceof Integer){
				System.out.println("int:"+obj);
			}else{
				System.out.println("Other:"+obj);
			}
		}
		
	}

}


2)Set接口

继承Collection,无序但不允许重复。

按照定义,Set接口继承Collection接口,而且它不允许集合中存在重复项。所有原始方法都是Collection中现成的,没有引入新方法。具体的Set实现类依赖添加的对象的equals()方法来检查等同性。

实现类:HashSet TreeSet

3)List接口

继承Collection,有序但允许重复,并引入位置下标。

List接口继承了Collection接口以定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。面向位置的操作包括插入某个元素或Collection的功能,还包括获取、除去或更改元素的功能。在List中搜索

元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置。(注:别小看这位置操作功能的添加,有很大的用处,如需要对集合内哪一个(位置)元素进行操作是,他们就束手无策了)

注意:

a)使用List(如ArrayList)时,不会自动调用hashCode()方法。因为在List中,重复了就重复了,不需判断,保证唯一性。

b)List中添加了下标index的功能,这样对List的修改可以利用set方法对指定位置的元素直接进行替换,不需要象Set那么复杂(要转换成数组才能修改,之后还要转换回去)。(验证上面我说的那点了吧)

c)Collection用Iterator迭代器,而List可以用ListIterator列表迭代器。前者只能next(),后者不但包含next()方法,还包含previous()方法。因此,如果要用List做类似书的翻页功能,不但可以向后翻,还可以向前翻。

实现类:LinkedList ArrayList

4)Map接口

Map接口不是Collection接口的继承。而是从自己的用于维护键-值关联的接口层次结构入手。按定义,该接口描述了从不重复的键到值的映射。

可以把这个接口方法分成三组操作:改变、查询和提供可选视图。

改变操作允许从映射中添加和除去键-值对。键和值都可以为null。但是,不能把Map作为一个键或值添加给自身。

Map.Entry接口(Entry就是Map接口中的内部类,所以写成这样):Map的entrySet()方法返回一个实现Map.Entry接口的对象Set集合,其中每个对象都是底层Map中一个特定的键-值对。

这个还是用图片比较形象,更容易理解


实现类:TreeMap HashMap

2、实现类

1)ArrayList类和Linkedlist类

使用两种类的哪一种取决于特定的需要:如果要支持随机访问,而不必在除尾部的任何位置插入或除去元素,那么,ArrayList提供了可选的集合。

但如果要频繁的从列表的中间位置添加和除去元素,而只要顺序的访问列表元素,那么LinkedList实现更好。

常用的几个方法:
boolean
add(E e)


将指定的元素添加到此列表的尾部。
void
add(int index,E element)


将指定的元素插入此列表中的指定位置。
E
get(int index)


返回此列表中指定位置上的元素。
boolean
isEmpty()


如果此列表中没有元素,则返回 true
E
remove(int index)


移除此列表中指定位置上的元素。
int
size()


返回此列表中的元素数。
E
set(int index,E element)


用指定的元素替代此列表中指定位置上的元素。
注:此外,LinkedList添加了一些处理列表两端元素的方法,使用这些方法,可以轻松地把LinkedList当作一个堆栈、队列或其它面向端点的数据结构。本身上就可以把LinkedList看做一个堆栈和队列,至于为什么可以分为这两种,注意看你怎么用里

面的方法而已。

void
addFirst(E e)


将指定元素插入此列表的开头。
void
addLast(E e)


将指定元素添加到此列表的结尾。
E
getFirst()


返回此列表的第一个元素。
E
getLast()


返回此列表的最后一个元素。
E
removeFirst()


移除并返回此列表的第一个元素。
E
removeLast()


移除并返回此列表的最后一个元素。

2)HashMap类和TreeMap类

使用两种类的哪一种取决于特定的需要:在Map中插入、删除和定位元素,HashMap是最好的选择。但如果要按顺序遍历键,那么TreeMap会更好。

使用HashMap要求添加的键类明确定义了hashCode()实现(助理解:Map.keySet返回的是键的Set集合,而Set集合对hashCode实现有限制,因此作为键的类也要遵守该限制)。有了TreeMap实现,添加到映射的元素一定是可排序的。

注意:HashMap和TreeMap都实现Cloneable接口。

3)HashSet类和TreeSet类

“集合框架”支持Set接口两种普通的实现:HashSet和TreeSet。在更多情况下,会使用HashSet存储重复自由的集合。考虑到效率,添加到HashSet的对象需要采用恰当分配散列码的方式来实现hashCode()方法。当需要从集合中以有序的方式抽

取元素时,TreeSet实现会有用处。为了能顺利进行,添加到TreeSet的元素必须是可排序的。

因为这个用的相对而言不是很多,在加上看多上面两大类,具体的自己看看API就会了。

四、集合排序

1、方法1

java.lang.Comparable接口适用于一个类有自然顺序的时候。假定对象集合是同一类型,该接口允许把集合排序成自然顺序。

该接口中的int compareTo( T obj )方法: 比较当前实例对象与对象obj,如果位于对象obj之前,返回负值;如果两个对象在排序中位置相同,则返回0;如果位于对象obj后面,则返回正值。

◆该排序方法的实现要点:

让被放置到容器的对象类实现Comparable接口。由其中所实现的方法compareTo( )决定对象之间的排列顺序。

2、方法2

java.util.Comparator接口适用于一个类有自然顺序的时候。假定对象集合是同一类型,该接口允许把集合排序成自然顺序。

该接口中的compare ( T o1, To2)方法: 比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负、零或正整数

◆该排序方法的实现要点:

让容器在构造时加入比较器对象。

◆中文排序问题:

比较函数对于英文字母与数字等ASCII码中的字符排序都没问题,但中文排序则明显不正确。这主要是Java中使用中文编码GB2312或GBK时,char型转换成int型的过程出现了比较大的偏差。这偏差是由compare方法导致的,因此我们可以自己实

现Comparator接口。另外,国际化问题可用Collator类来解决。

java.text.Collator类,提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。



import java.text.CollationKey;
import java.text.Collator;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class MySort2 {

public staticvoid main(String[] args) {
sort2();//中文排序

}


private staticvoid sort2() {
TreeMap map = new TreeMap( new MyCmp2() ); //给TreeMap集合外加一个我们自己写的比较器,由比较器来决定元素的排序方式
map.put("周平","1002" );
map.put("周平2", "1112");
map.put("张军1", newEmployee("Mike",26));
map.put("张军2", newEmployee("Rose",23));

Set entries = map.entrySet();
Iterator it = entries.iterator();
while(it.hasNext()){
Map.Entry e = (Map.Entry)it.next();
System.out.println(e.getKey()+","+e.getValue());
}
}

}

class MyCmp2 implements Comparator{
Collator collator = Collator.getInstance();
@Override
publicint compare(Object o1, Object o2) {
CollationKey key1 = collator.getCollationKey(o1.toString());
CollationKey key2 = collator.getCollationKey(o2.toString());
return key2.compareTo(key1);
}
}


3、集合排序的应用场合

在JDK1.2中,有14个类实现了Comparable接口,这些类中指定的自然排序如下:

1)BigDecimal,BigInteger,Byte,Double,Float,Integer,Long,Short按数字大小排序

2)Character 按Unicode值的数字大小排序

3)CollationKey 按语言环境敏感的字符串排序

4)Date 按年代排序

5)File 按系统特定的路径名的全限定字符的Unicode值排序

6)ObjectStreamField 按名字中字符的Unicode值排序

7)String 按字符串中字符Unicode值排序

注:如果一个类不能或不便于实现java.lang.Comparable接口,则可以用实现比较器Comparator接口的方法提供自己的排序行为。同样,如果缺省Comparable行为满足不了工程需要,也可以提供自己的Comparator。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: