JAVA学习笔记(8)——对象群体的组织

一、对象数组
1.数组
–在Java提供的存储及随机访问对象序列的各种方法中,数组是效率最高的一种
类型检查
边界检查
–优点
数组知道其元素的类型
编译时的类型检查
大小已知
–代价
数组对象的大小是固定的,在生存期内大小不可变
2.对象数组
–数组元素是类的对象
–所有元素具有相同的类型
–每个元素都是一个对象的引用
3.排序
–按照预先规定的准则(如升序或降序等),把数据有次序地排列起来
–已经设计出许多排序算法,常用的排序算法有
选择排序
插入排序
交换排序
(1)选择排序
–先在未排序序列中选一个最小元素,作为已排序子序列
–然后再重复地从未排序子序列中选取一个最小元素,把它加到已经排序的序列中,作为已排序子序列的最后一个元素

–直到把未排序子序列中的元素处理完为止

二、集合
数组的优点
–是Java提供的随机访问对象序列的最有效方法
–是一个简单的线性序列,访问元素的速度较快
数组的缺点
–大小自创建以后就固定了,在其整个生存期内
其大小不可改变
–数组元素只能是同一类型
集合
–可动态改变其大小
–可在序列中存储不同类型的数据
1.概念
–把具有相同性质的一类东西,汇聚成一个整体
–在Java中有很多与集合有关的接口及类
–它们被组织在以Collection及Map接口为根的层次结构中,称为集合框架
2.Java集合框架(Java Collections Framework)
–为表示和操作集合而规定的一种统一的标准的体系结构
–提供了一些现成的数据结构可供使用,程序员可以利用集合框架快速编写代码,并获得优良性能
–包含三大块内容
(1)对外的接口:表示集合的抽象数据类型,使集合的操作与表示分开
集合框架接口
– 声明了对各种集合类型执行的一般操作
– 包括Collection、Set、List、SortedSet、Map、Sorted Map
– 基本结构如图
类层次如图,包括4个接口、4个抽象类及6个具体类
a、Collection接口
–声明了一组操作成批对象的抽象方法:查询方法、修改方法
–查询方法
int size() –返回集合对象中包含的元素个数
boolean isEmpty() –判断集合对象中是否还包含元素,如果没有任何元素,则返回true
boolean contains(Object obj) –判断对象是否在集合中
boolean containsAll(Collection c) –判断方法的接收者对象是否包含集合中的所有元素
修改方法包括
boolean add(Object obj) –向集合中增加对象
boolean addAll(Collection c) –将参数集合中的所有元素增加到接收者集合中
boolean remove(Object obj) –从集合中删除对象
boolean removeAll(Collection c) -将参数集合中的所有元素从接收者集合中删除
boolean retainAll(Collection c) –在接收者集合中保留参数集合中的所有元素,其它元素都删除
void clear() –删除集合中的所有元素
b.Set接口
– 扩展了Collection
– 禁止重复的元素,是数学中“集合”的抽象
– 对equals和hashCode操作有了更强的约定,如果两个Set对象包含同样的元素,二者便是相等的
– 实现它的两个主要类是哈希集合(HashSet)及树集合(TreeSet)
c.SortedSet接口
– 一种特殊的Set
– 其中的元素是升序排列的,还增加了与次序相关的操作
– 通常用于存放词汇表这样的内容
d.List接口
–扩展了Collection
–可包含重复元素
–元素是有顺序的,每个元素都有一个index值(从0开始)标明元素在列表中的位置
–实现它的四个主要类是
Vector
ArrayList:一种类似数组的形式进行存储,因此它的随机访问速度极快
LinkedList:内部实现是链表,适合于在链表中间需要频繁进行插入和删除操作
栈Stack
e.Map接口
– 不是Collection接口的继承
– 用于维护键/值对(key/value pairs)
– 描述了从不重复的键到值的映射,是一个从关键字到值的映射对象
– 其中不能有重复的关键字,每个关键字最多能够映射到一个值
f.SortedMap接口
– 一种特殊的Map,其中的关键字是升序排列的
– 与SortedSet对等的Map,通常用于词典和电话目录等
(2)接口的实现:指实现集合接口的Java类,是可重用的数据结构
–Collection没有直接的实现,只是作为其他集合
接口的最小公分母
–除Collection 以外,其余五个接口都有实现
–主要的实现有
Set->HashSet
SortedSet->TreeSet
List->Vector/ArrayList/LinkedList
Map->HashMap
SortedMap->TreeMap
(3)对集合运算的算法:是指执行运算的方法,例如在集合上进行查找和排序
–大多数算法都是用于操作List对象
–有两个(min和max)可用于任意集合对象
a.排序算法sort
–对List重新排序,使其中的元素按照某种次序关系升序排列
–有两种形式
简单形式只是将元素按照自然次序排列
第二种形式需要一个附加的Comparator对象作为参数,用于规定比较规则,可用于实现反序或特殊次序排序
b.洗牌算法shuffle
其作用与排序算法恰好相反,它打乱List中的任何次序。也就是说以随机方式重排元素,任何次序出现的几率都是相等的
在实现偶然性游戏的时候,这个算法很有用,例如洗牌
c.常规数据处理算法
reverse::将一个List中的元素反向排列
fill:用指定的值覆写List中的每一个元素,这个操作在重新初始化List时有用
copy::接受两个参数,目标List和源List,将源中的元素复制到目标,覆写其中的内容。目标List必须至少与源一样长,如果更长,则多余的部分内容不受影响
d.查找算法binarySearch
使用二分法在一个有序的List中查找指定元素
有两种形式
第一种形式假定List是按照自然顺序升序排列的
第二种形式需要增加一个Comparator对象,表示比较规则,并假定List是按照这种规则排序的。
e.寻找最值——用于任何集合对象
min和max算法返回指定集合中的最小值和最大值
这两个算法分别都有两种形式
简单形式按照元素的自然顺序返回最值

另一种形式需要附加一个Comparator对象作为参数,并按照Comparator对象指定的比较规则返回最值

            数组实用方法
Arrays类
–Java集合框架提供了一套专门用于操作数组的实用方法,它们作为静态方法存在该类中
–还包括可以将数组视为列表(List)的静态工厂
–常用方法
fill (type[] a, type val):给数组填充,就是简单地把一个数组全部或者某段数据填成一个特殊的值
equals (type[] a, type[] b):实现两个数组的比较,相等时返回true
sort (type[] a):对数组排序
binarySearch ():对数组元素进行二分法查找

Arrays.asList (Object[] a):实现数组到ArrayList的转换

三、向量(Vector,ArrayList)

Vector/ArrayList
–实现了Collection接口的具体类
–能够存储任意对象,但通常情况下,这些不同类型的对象都具有相同的父类或接口
–不能存储基本类型(primitive)的数据,除非将这些数据包裹在包裹类中
–其容量能够根据空间需要自动扩充
–增加元素方法的效率较高,除非空间已满,在这种情况下,在增加之前需要先扩充容量
Vector方法是同步的,线程安全
ArrayList方法是非同步的,效率较高
(1)构造方法
a.Vector类的构造方法
– Vector myVector = new Vector(); //初始容量为10 
– Vector myVector = new Vector(int cap); 
– Vector myVector = new Vector(Collection col);
以参数col中的元素进行初始化
也可用数组元素生成,但需先将数组转换成List对象,如
String[] num = {"one", "two", "three", "four", "five"}; 
Vector aVector = new Vector(java.util.Arrays.asList(num));
b.ArrayList的构造方法与Vector类似
– ArrayList myList = new ArrayList(); 
– ArrayList myList = new ArrayList(int cap); 
– ArrayList myList = new ArrayList(Collection col);
(2)常用方法
a.void add(Object obj)——添加一个对象,如
Vector teamList = new Vector(); 
teamList.add("Zhang Wei"); 
teamList.add("Li Hong"); 
b.boolean addAll(Collection col)——添加整个集合,如果接收者对象的结果有变化,则返回true,如
Vector teamList = new Vector(); 
teamList.add("Zhang Wei"); 
teamList.add("Li Hong"); 
Vector yourList = new Vector(); 
yourList.addAll(teamList);
c.int size()——返回元素的个数。
d.boolean isEmpty()——如果不含元素,则返回true
e.Object get(int pos)——返回指定位置的元素,如
Vector teamList = new Vector(); 
teamList.add("Zhang Wei"); 
teamList.add("Li Hong"); 
teamList.add("Yu Hongshu"); 
teamList.get(1); // 返回"Li Hong" 
teamList.get(3); // 产生例外ArrayIndexOutOfBoundsException
f.void set(int pos, Object obj)——用参数对象替换指定位置的对象,如
Vector teamList = new Vector(); 
teamList.add("Zhang Wei"); 
teamList.add("Li Hong"); 
teamList.add("Yu Hongshu"); 
teamList.set(2, "Liu Na"); 
System.out.println(teamList); // 显示[Zhang Wei, Li Hong, Liu Na]
teamList.set(3,"Ma Li"); // 产生例外ArrayIndexOutOfBoundsException
g.boolean remove(Object obj)——去除给定对象的第一次出现,如果找到了对象,则返回true。去除一个对象后,其后面的所有对象都依次向前移动。如
Vector teamList = new Vector();
teamList.add("Zhang Wei");
teamList.add("Li Hong"); 
teamList.add("Yu Hongshu"); 
teamList.remove("Li Hong");
teamList.remove("Wang Hong");//不做任何事,也不出现错误
System.out.println(teamList); // 显示[Zhang Wei,Yu Hongshu]
h.Object remove(int pos)——去除给定位置的元素,并返回被去除的对象。如
Vector teamList = new Vector();
teamList.add("Zhang Wei");
teamList.add("Li Hong"); 
teamList.add("Yu Hongshu");
teamList.remove(0); //去除Zhang Wei
teamList.remove(0); //去除Li Hong
System.out.println(teamList); // 显示[Yu Hongshu]
teamList.remove(1); //产生例外ArrayIndexOutOfBoundsException
i.boolean removeAll(Collection col)——从接收者对象中去除所有在参数对象中出现的元素,如果接收者对象的结果有变化,则返回true。如
VectorteamList= new Vector();
teamList.add("Zhang Wei");
teamList.add("Li Hong"); 
teamList.add("Yu Hongshu");
Vector yourList = new Vector();
yourList.add("Yu Hongshu");
yourList.add("He Li"); 
yourList.add("Zhang Wei"); 
teamList.removeAll(yourList);
System.out.println(teamList); // 显示[Li Hong]
j.void clear()——去除所有的元素
k.boolean contains(Object obj)——返回是否包含指定的对象,如果包含则返回true;否则,返回false
l.boolean containsAll(Collection col)——返回是否包含参数col中的所有对象
m.int indexOf(Object obj)——返回给定对象在Vector/ArrayList中第一次出现的位置,如不存在,则返回-1。如
Vector teamList = new Vector();
teamList.add("Zhang Wei");
teamList.add("Li Hong"); 
teamList.indexOf("Li Hong"); // 返回1。
teamList.indexOf("Zhang Li"); // 返回-1。
n.Enumeration elements()——返回包含Vector中所有元素的Enumeration类对象。该方法只能应用于Vector对象,不能应用于ArrayList对象。如
Vector teamList = new Vector();
teamList.add("Zhang Wei");
teamList.add("Li Hong"); 
teamList.add("Yu Hongshu");
teamList.elements(); // 返回Enumeration类对象。
o.Iterator iterator()——返回包含Vector/ArrayList中所有元素的Iterator类对象
(3)使用Vector存取对象
a.当使用get()方法取出Vector中的元素时,返回的类型都是Object类型。Vector的使用者需要记住存入对象的具体类型,当使用get()方法取出后,再塑型成其本来的类型。例如,创建Customer类对象的Vector如下:
String[]names = {"Zhang", "Li", "Wang", "Zhao"}; 
Vector v = new Vector(); 
for (int i=0; i<names.length; i++) { 
Customer c = new Customer(); 
c.setName(names[i]); 
v.add(c);
}
//集合类对象中每个元素的遍历方法
for (int i=0; i<v.size();i++) { 
Customer c = (Customer) v.get(i); //使用get()方法将Customer对象从Vector中取出后,需要再塑型成Customer类。
System.out.println(c.getName()); 
}
b.与所有的集合类一样,Vector不能存储原始类型(primitive)的数据,如果要存储,则需要使用包裹类。例如,
Vector rateVector = new Vector(); 
double[]rates = {36.25, 25.4, 18.34, 35.7,23.78}; 
for (int i=0; i<rates.length; i++) 
rateVector.add(new Double(rates[i]));

double sum = 0.0; 
for (int i=0; i<rateVector.size();i++) 
sum + = ((Double)rateVector.get(i)).doubleValue(); //当从Vector中取出时,需要塑型成相应的包裹类型,之后再还原为原始类型

return sum;

四、Enumeration及Iterator接口

– 能够从集合类对象中提取每一个元素,并提供了用于遍历元素的方法
– Java中的许多方法(如elements())都返回Enumeration类型的对象,而不是返回集合类对象
– Enumeration接口不能用于ArrayList对象,而Iterator接口既可以用于ArrayList对象,也可以用于Vector对象
(1)Enumeration接口(1.0版)
– 提供了两个实例方法
hasMoreElements() ——判断是否还有剩下的元素;
nextElement() ——取得下一个元素。
– 遍历集合类对象v中的每个元素可使用下面代码完成:
Enumeration e = v.elements(); 
while (e.hasMoreElements()) { 
Customer c = (Customer)v.nextElement(); 
System.out.println(c.getName()); 
}
(2)Iterator接口(1.2版,替代Enumeration)
– 也是一个遍历集合元素的工具,是对Enumeration接口的改进,因此在遍历集合元素时,优先选用Iterator接口
– 与Enumeration不同,具有从正在遍历的集合中去除对象的能力
– 具有如下三个实例方法,可见相对于Enumerationo接口简化了方法名
hasNext()——判断是否还有元素
next()——取得下一个元素

remove() ——去除一个元素。注意是从集合中去除最后调用next()返回的元素,而不是从Iterator类中去除

五、Map接口及其类层次

Map接口
–以该接口为根的集合类
用于存储“关键字”(key)和“值”(value)的元素对,其中每个关键字映射到一个值
当需要通过关键字实现对值的快速存取时使用
–声明的抽象方法主要有
(1)查询方法
– int size()——返回Map中的元素个数
– boolean isEmpty() ——返回Map中是否包含元素,如不包括任何元素,则返回true
– boolean containsKey(Object key)——判断给定的参数是否是Map中的一个关键字(key)
– boolean containsValue(Object val)——判断给定的参数是否是Map中的一个值(value)
– Object get(Object key)——返回Map中与给定关键字相关联的值(value)
– Collection values()——返回包含Map中所有值(value)的Collection对象
– Set keySet()——返回包含Map中所有关键字(key)的Set对象
– Set entrySet()——返回包含Map中所有项的Set对象
(2)修改方法
– Object put(Object key, Object val)——将给定的关键字(key)/值(value)对加入到Map对象中。其中关键字(key)必须唯一,否则,新加入的值会取代Map对象中已有的值
– void putAll(Map m)——将给定的参数Map中的所有项加入到接收者Map对象中
– Object remove(Object key)——将关键字为给定参数的项从Map对象中删除
– void clear()——从Map对象中删除所有的项
–两个主要实现类——HashTable (1.0)、HashMap (1.2)
(1)哈希表
– 也称为散列表,是用来存储群体对象的集合类结构,其两个常用的类是HashTable及HashMap
– 哈希表存储对象的方式与前面所讲的数组,Vector及ArrayList不同
数组,Vector及ArrayList中对象的存储位置是随机的,即对象本身与其存储位置之间没有必然的联系。因此查找一个对象时,只能以某种顺序(如顺序查找,二分查找)与各个元素进行比较,如果数组或向量中的元素数量很庞大时,查找的效率必然降低
哈希表中,对象的存储位置和对象的关键属性k之间有一个特定的对应关系f,我们称之为哈希(Hash)函数。它使每个对象与一个唯一的存储位置相对应。因而在查找时,只要根据待查对象的关键属性k,计算f(k)的值即可知其存储位置
(2)哈希表相关的一些主要概念
– 容量(capacity)——哈希表的容量不是固定的,随对象的加入,其容量可以自动扩充
– 关键字/键(key)——每个存储的对象都需要有一个关键字key,key可以是对象本身,也可以是对象的一部分(如对象的某一个属性)
– 哈希码(hash code)——要将对象存储到HashTable,就需要将其关键字key映射到一个整型数据,称为key的哈希码(hash code)
– 哈希函数(hash function)——返回对象的哈希码
– 项(item)——哈希表中的每一项都有两个域:关键字域key及值域value(即存储的对象)。key及value都可以是任意的Object类型的对象,但不能为空(null),HashTable中的所有关键字都是唯一的
– 装填因子(load factor)——(表中填入的项数)/(表的容量)
(3)HashTable的常用方法
a.构造方法
– Hashtable( ); // 初始容量为101,最大装填因子为0.75
– Hashtable(int capacity);
– Hashtable(int capacity, float maxLoadFactor); 
b.Object put(Object key, Object value)——值value以key为其关键字加入到哈希表中,如果此关键字在表中不存在,则返回null,否则返回表中存储的value
Hashtable aPhoneBook = new Hashtable(); 
aPhoneBook.put("Zhang Lei", "010-84256712"); 
aPhoneBook.put("Zhu Yongqin", "010-82957788"); 
aPhoneBook.put("Liu Na", "010-80791234"); 
System.out.println(aPhoneBook); // 显示{ Liu Na=010-80791234, Zhu Yongqin=010-82957788, Zhang Lei=010-84256712 }
c.Object get(Object key)——返回关键字为key的值value,如果不存在,则返回null。如
Hashtable aPhoneBook = new Hashtable(); 
aPhoneBook.put("Zhang Lei", "010-84256712"); 
aPhoneBook.put("Zhu Yongqin", "010-82957788"); 
aPhoneBook.get("Zhang Lei");  // 返回"010-84256712"
aPhoneBook.get("Zhu Yongqin");  // 返回"010-82957788"
aPhoneBook.get("Liu Ling");  // 返回null
d.Object remove(Object key)——将键/值对从表中去除,并返回从表中去除的值,如果不存在,则返回null。如
HashtableaPhoneBook = new Hashtable(); 
aPhoneBook.put("Zhu Yongqin", "010-82957788"); 
aPhoneBook.put("Liu Na", "010-80791234");
aPhoneBook.remove("Zhu Yongqin");
aPhoneBook.remove("010-80791234"); // 不出错,但返回null
System.out.println(aPhoneBook); // 显示{ Liu Na=010-80791234}
e.boolean isEmpty()——判断哈希表是否为空
f.boolean containsKey(Object key)——判断给定的关键字是否在哈希表中
g.boolean contains(Object value)——测试此映射表中是否存在与指定值关联的键
h.boolean containsValue(Object value)——如果Hashtable 将一个或多个键映射到此值,则返回true 
i.void clear()——将哈希表清空
j.Enumeration elements()——返回包含值的Enumeration对象
k.Enumeration keys()——返回包含关键字的Enumeration对象

HashMap类与HashTable类很相似,只是HashTable类不允许有空的关键字,而HashMap类允许

六、J2SE 5.0中的泛型
在以前的JDK的版本中,很多集合框架的函数接受一个Object参数。
–collections是一个能持有任何对象的多用途工具,但带来了不良的后果。
泛型的好处
–编译时的严格类型检查。
–消除了绝大多数的类型转换。
泛型类如何定义
public class TestGenerics<E>

Collection<E> col;
public void doSth(E elem)

col.add(elem);
// ...
}
}
泛型方法的定义
public static <T extends SomeClass> void add (Collection<T> c, T elem) {
c.add(elem);
}

猜你喜欢

转载自blog.csdn.net/sinat_38756080/article/details/80450209