在JDK API中专门设计了一组类,这组类的功能就是实现各种各样方式的数据存储,这样一组专门用来存储其它对象的类,一般被称为对象容器类,简称容器类,这组类和接口的设计结构也被统称为集合框架(Collection Framework)。

这组类和接口都包含在java.util包中。

为了使整个集合框架中的类便于使用,在设计集合框架时大量的使用接口,实际实现的功能类实现对应的接口,这样可以保证各个集合类的使用方式保持统一。

在集合框架中,提供的存储方式共有两种:

1、按照索引值操作数据

在这种存储方式中,为每个存储的数据设定一个索引值,存储在容器中的第一个元素索引值是0,第二个索引值是1,依次类推。在操作数据时按照索引值操作对应的数据,实现这种方式的集合类都实现java.util.Collection接口。

2、按照名称操作数据

在这种存储方式中,为每个存储的数据设定一个名称(任意非null的对象都可以作为名称),以后按照该名称操作该数据,要求名称不能重复,每个名称对应唯一的一个值。这种存储数据的方式也称作名称-数值对,也就是名值对存储。实现这种方式的几个类都实现java.util.Map接口。

这里“按照索引值操作数据”的存储方式,又按照容器内部是否能够存储重复的元素,划分成两类:

1、允许存储重复元素。

这种存储方式中,所有的类都实现了java.util.List接口。

2、不允许存储重复元素。

这种存储方式中,所有的类都实现了java.util.Set接口。

这样,集合框架中的类就分成了三大类:

1、List系列

该系列中的类按照索引值来操作数据,允许存放重复的元素。

2、Set系列

该系列中的类按照索引值来操作数据,不允许存放重复的元素。

3、Map系列

该系列中的类按照名称来操作数据,名称不允许重复,值可以重复,一个名称对应一个唯一的值。

而 在数据结构中,实现数据的存储又可以使用不同的数据结构类型进行存储,例如数组、链表、栈、队列和树等,则以上三类集合框架可以使用不同的数据结构类进行 实现,使用每种数据结构则具备该中数据结构的特点。例如使用数组则访问速度快,使用链表则便于动态插入和删除等,这样就造成了集合框架的复杂性。

另外,在将对象存储到集合类中,为了加快存储的速度,要求被存储对象的类中必须覆盖equals方法和hashCode方法。

对于这些集合类,下面按照以上三个系列的顺序一一进行说明。

9.6.3.1 List系列

List系列的类均实现List接口,大部分的类都以List作为类名的后缀,也有部分该体系中的类命名比较特殊。

该系列中的类,比较常见的有ArrayList和LinkedList两个。其中ArrayList是以数组为基础实现的List,而LinkedList则是以链表为基础实现的List,ArrayList拥有数组的优点,而LinkedList拥有链表的优点。

由于该体系中的类均实现List接口,所以在这些类的内部,相同的功能方法声明是保持一致的,下面进行一一介绍:

a、add方法

boolean add(Object o)

该方法的作用是追加对象o到已有容器的末尾。

另外一个add方法:

void add(int index, Object element)

该方法的作用是将对象element插入到容器中索引值为index的位置,原来位于该位置的对象以及后续的内容将依次向后移动。

b、addAll方法

boolean addAll(Collection c)

该方法的作用是将容器对象c中的每个元素依次添加到当前容器的末尾。

另外一个addAll方法:

boolean addAll(int index, Collection c)

该方法的作用是将容器对象c中的第一个元素插入到当前容器中索引值为index的位置,第二个元素插入到当前容器中索引值为index+1的位置,依次类推。而当前容器中原来位于index以及index索引值以后的元素则依次向后移动。

c、get方法

Object get(int index)

该方法的作用是返回当前容器对象中索引值为index的元素的内容。

d、indexOf方法

int indexOf(Object o)

该方法的作用是查找当前容器中是否存在对象o,如果存在则返回该对象第一次出现位置的索引值,如果不存在则返回-1。

另外一个方法lastIndexOf则是从末尾向前查找,返回从末尾向前第一次出现位置的索引值,如果不存在则返回-1。

e、remove方法

Object remove(int index)

该方法的作用是删除索引值为index的对象的内容,如果删除成功则返回被删除对象的内容。

另外一个remove方法:

boolean remove(Object o)

该方法的作用是删除对象内容为o的元素,如果相同的对象有多个,则只删除索引值小的对象。如果删除成功则返回true,否则返回false。

无论使用哪一个remove方法,类内部都自动移动将被删除位置后续的所有元素向前移动,保证索引值的连续性。

f、set方法

Object set(int index, Object element)

该方法的作用是修改索引值为index的内容,将原来的内容修改成对象element的内容。

g、size方法

int size()

该方法的作用是返回当前容器中已经存储的有效元素的个数。

h、toArray方法

Object[] toArray()

该方法的作用是将当前容器中的元素按照顺序转换成一个Object数组。

下面是一个简单的以ArrayList类为基础实现的List系列中类基本使用的示例,代码如下:

import java.util.*;

/**

* 以ArrayList类为基础演示List系列类的基本使用

*/

public class ArrayListUse {

public static void main(String[] args) {

//容器对象的初始化

List list = new ArrayList();

//添加数据

list.add("1");

list.add("2");

list.add("3");

list.add("1");

list.add("1");

//插入数据

list.add(1,"12");

//修改数据

list.set(2, "a");

//删除数据

list.remove("1");

//遍历

int size = list.size(); //获得有效个数

//循环有效索引值

for(int i = 0;i < size;i++){

System.out.println((String)list.get(i));

}

}

}

该程序的运行结果为:

12

a

3

1

1

在List系列中,还包含了Stack(栈)类和Vector(向量)类,Stack类除了实现List系列的功能以外,还实现了栈的结构,主要实现了出栈的pop方法和入栈的push方法。

而Vector类由于需要兼容老版本JDK中缘故,所以在实现的方法中需要提供老版本Vector类中对应的方法,这样导致Vector类中相同或类似的功能方法一般是成对出现的。

Set系列

Set系列中的类都实现了Set接口,该系列中的类均以Set作为类名的后缀。该系列中的容器类,不允许存储重复的元素。也就是当容器中已经存储一个相同的元素时,无法实现添加一个完全相同的元素,也无法将已有的元素修改成和其它元素相同。

Set系列中类的这些特点,使得在某些特殊场合的使用比较适合。

该系列中常见的类有:

1、CopyOnWriteArraySet

以数组为基础实现的Set类。

2、HashSet

以哈希表为基础实现的Set类。

3、LinkedHashSet

以链表为基础实现的Set类。

4、TreeSet

以树为基础实现的Set类。

以不同的数据结构类型实现的Set类,拥有不同数据结构带来的特性,在实际使用时,根据逻辑的需要选择合适的Set类进行使用。

Set系列中的类的方法和List系列中的类的方法要比List系列中少很多,例如不支持插入和修改,而且对于Set系列中元素的遍历也需要转换为专门的Iterator(迭代器)对象才可以进行遍历,遍历时顺序和Set中存储的顺序会有所不同。

下面是以HashSet类为基础实现的示例代码,代码如下:

import java.util.*;

/**

* 以HashSet为基础演示Set系列类的基本使用

*/

public class HashSetUse {

public static void main(String[] args) {

//容器对象的初始化

Set set = new HashSet();

//添加元素

set.add("1");

set.add("2");

set.add("3");

set.add("1");

set.add("1");

//删除数据

//set.remove("1");

//遍历

Iterator iterator = set.iterator();

while(iterator.hasNext()){

System.out.println((String)iterator.next());

}

}

}

该程序的运行结果为:

3

2

1

Map系列

Map系列中的类都实现了Map接口,该系列中的部分类以Map作为类名的后缀。该系列容器类存储元素的方式和以上两种完全不同。

Map提供了一种使用“名称:值”这样的名称和数值对存储数据的方法,在该存储方式中,名称不可以重复,而不同的名称中可以存储相同的数值。具体这种存储的格式将在示例代码中进行实现。

在这种存储结构中,任何不为null的对象都可以作为一个名称(key)来作为存储的值(value)的标识,使用这种形式更利于存储比较零散的数据,也方便数据的查找和获得。Map类中存储的数据没有索引值,系统会以一定的形式索引存储的名称,从而提高读取数据时的速度。

该系列中常见的类有:

1、HashMap

以Hash(哈希表)为基础实现的Map类。

2、LinkedHashMap

以链表和Hash(哈希表)为基础实现的Map类。

3、TreeMap

以树为基础实现的Map类。

和上面的结构类似,以不同的数据结构实现的Map类,拥有不同数据结构的特点,在实际的项目中使用时,根据需要选择合适的即可。

该系列的类中常见的方法如下:

a、get方法

Object get(Object key)

该方法的作用是获得当前容器中名称为key的结构对应的值。

b、keySet方法

Set keySet()

该方法的作用是返回当前容器中所有的名称,将所有的名称以Set的形式返回。使用这个方法可以实现对于Map中所有元素的遍历。

c、put方法

Object put(Object key, Object value)

该方法的作用是将值value以名称key的形式存储到容器中。

d、putAll方法

void putAll(Map t)

该方法的作用是将Map对象t中的所有数据按照原来的格式存储到当前容器类中,相当于合并两个Map容器对象。

e、remove方法

Object remove(Object key)

该方法的作用是删除容器中名称为key的值。

f、size方法

int size()

该方法的作用是返回当前日期中存储的名称:值数据的组数。

g、values方法

Collection values()

该方法的作用是返回当前容器所有的值组成的集合,以Collection对象的形式返回。

下面是一个简单的示例,在该示例中演示Map系列类的基本使用,代码如下:

import java.util.*;

/**

* 以HashMap为基础演示Map系列中类的使用

*/

public class HashMapUse {

public static void main(String[] args) {

//容器对象的初始化

Map map = new HashMap();

//存储数据

map.put("苹果", "2.5");

map.put("桔子", "2.5");

map.put("香蕉", "3");

map.put("菠萝", "2");

//删除元素

map.remove("桔子");

//修改元素的值

map.put("菠萝", "5");

//获得元素个数

int size = map.size();

System.out.println("个数是:" + size);

//遍历Map

Set set = map.keySet();

Iterator iterator = set.iterator();

while(iterator.hasNext()){

//获得名称

String name = (String)iterator.next();

//获得数值

String value = (String)map.get(name);

//显示到控制台

System.out.println(name + ":" + value);

}

}

}

该程序的运行结果为:

个数是:3

香蕉:3

菠萝:5

苹果:2.5

使用示例

如前所述,集合框架中的类只是提供了一种数据存储的方式,在实际使用时,可以根据逻辑的需要选择合适的集合类进行使用。

下面以一个字符串计算的示例演示集合类的实际使用。

该程序的功能为计算一个数字字符串,例如”1+2*31-5”、”12*30/34-450”等,的计算结果,在该示例中支持四则运算,但是不支持括号。本示例中计算的字符串要求合法。

该程序实现的原理是:首先按照运算符作为间隔,将字符串差分为数字字符串和运算符字符串的序列,由于分拆出的字符串数量不固定,所以存储到List系列的Vector容器中,然后按照运算符的优先级进行计算。

该程序的代码如下:

import java.util.*;

/**

* 计算字符串的值

*/

public class CalcStr {

public static void main(String[] args) {

String s = "1+20*3/5";

double d = calc(s);

System.out.println(d);

}

/**

* 计算字符串的值

* @param s 需要计算的字符串

* @return 计算结果

*/

public static double calc(String s){

//拆分字符串

Vector v = split(s);

//print(v); //测试代码

//计算字符串

double d = calcVector(v);

return d;

}

/**

* 将字符串拆分为数字和运算符。

* 例如:"1+23*4"则拆分为:"1"、"+"、"23"、"*"和"4"

* @param s 需要拆分的字符串

* @return 拆分以后的结果

*/

private static Vector split(String s){

Vector v = new Vector();

String content = "";

int len = s.length(); //字符串长度

char c;

for(int i = 0;i < len;i++){

c = s.charAt(i);

//判断是否为运算符

if(c == '+' ||

c == '-' ||

c == '*' ||

c == '/'){

//存储数字

v.add(content);

//存储运算符

v.add("" + c);

//清除已有字符串

content = "";

}else{

content += c; //连接字符串

}

}

v.add(content); //添加最后一个数字

return v;

}

/**

* 测试代码,输出拆分以后的结果

* @param v 需要打印的Vector对象

*/

private static void print(Vector v){

int size = v.size();

for(int i = 0;i < size;i++){

System.out.println((String)v.get(i));

}

}

/**

* 计算Vector中的数据

* @param v 存储拆分后字符串的Vector

* @return 计算结果

*/

private static double calcVector(Vector v){

int index1;

int index2;

//计算乘除

while(true){

index1 = v.indexOf("*"); //乘号索引值

index2 = v.indexOf("/"); //除号索引值

//无乘除符号

if(index1 == - 1 && index2 == -1){

break; //结束循环

}

//如果有乘号

if(index1 != -1){

//没有除号或乘号在前

if(index2 == -1 || index1 < index2){

String s1 = (String)v.get(index1 - 1); //第一个数字

String opr = (String)v.get(index1); //运算符

String s2 = (String)v.get(index1 + 1); //第二个数字

//计算

String answer = calc(s1,s2,opr);

//计算以后的处理

handle(answer,index1 - 1,v);

}

}

//有除号

if(index2 != -1){

//没有乘号或除号在前

if(index1 == -1 || index2 < index1){

String s1 = (String)v.get(index2 - 1); //第一个数字

String opr = (String)v.get(index2); //运算符

String s2 = (String)v.get(index2 + 1); //第二个数字

//计算

String answer = calc(s1,s2,opr);

//计算以后的处理

handle(answer,index2 - 1,v);

}

}

}

//计算加

int index3 = v.indexOf("+");

while(index3 != -1){ //有加号

String s1 = (String)v.get(index3 - 1); //第一个数字

String opr = (String)v.get(index3); //运算符

String s2 = (String)v.get(index3 + 1); //第二个数字

//计算

String answer = calc(s1,s2,opr);

//计算以后的处理

handle(answer,index3 - 1,v);

//获得下一个加号的位置

index3 = v.indexOf("+");

}

//计算减

index3 = v.indexOf("-");

while(index3 != -1){ //有加号

String s1 = (String)v.get(index3 - 1); //第一个数字

String opr = (String)v.get(index3); //运算符

String s2 = (String)v.get(index3 + 1); //第二个数字

//计算

String answer = calc(s1,s2,opr);

//计算以后的处理

handle(answer,index3 - 1,v);

//获得下一个减号的位置

index3 = v.indexOf("-");

}

//反馈结果

String data = (String)v.get(0);

return Double.parseDouble(data);

}

/**

* 计算两个字符串类型的值运算结果

* @param number1 数字1

* @param number2 数字2

* @param opr 运算符

* @return 运算结果

*/

private static String calc(String number1,String number2,String opr){

//将字符串转换为数字

double d1 = Double.parseDouble(number1);

double d2 = Double.parseDouble(number2);

//判断运算符

if(opr.equals("+")){

return "" + (d1 + d2);

}

if(opr.equals("-")){

return "" + (d1 - d2);

}

if(opr.equals("*")){

return "" + (d1 * d2);

}

if(opr.equals("/")){

return "" + (d1 / d2);

}

return "0"; //运算符错误时返回0

}

/**

* 计算以后的处理

* @param answer 计算结果

* @param index 参与计算的三个字符串中第一个字符串的起始位置

* @param v 存储字符串的容器

*/

private static void handle(String answer,int index,Vector v){

//删除计算过的字符串

for(int i = 0;i < 3;i++){

v.remove(index);

}

//将计算结果插入到index位置

v.insertElementAt(answer, index);

}

}

该程序的运行结果为:

13.0

java的集合类【转】的更多相关文章

  1. java基础 集合类

    java集合类主要有以下集中: List结构的集合类: ArrayList类, LinkedList类, Vector类, Stack类 Map结构的集合类: HashMap类,Hashtable类 ...

  2. Java的集合类

    转自:Q.Mr的博客 http://www.cnblogs.com/zrtqsk/p/3472258.html (本人第一次写博客,部分内容有参照李刚老师的疯狂java系列图书,如有遗漏错误,请多指教 ...

  3. 首先java中集合类主要有两大分支

    本文仅分析部分原理和集合类的特点,不分析源码,旨在对java的集合类有一个整体的认识,理解各个不同类的关联和区别,让大家在不同的环境下学会选择不同的类来处理. Java中的集合类包含的内容很多而且很重 ...

  4. Java:集合类的区别详解

    Java中集合类的区别 Array是数组,不在集合框架范畴之内,一旦选定了,它的容量大小就不能改变了,所以通常在编程中不选用数组来存放. 集合 : 集合对象:用于管理其他若干对象的对象 数组:长度不可 ...

  5. java中集合类中Collection接口中的List接口的常用方法熟悉

    1:集合类,在java语言中的java.util包提供了一些集合类,这些集合类又被称作容器. 2:区别集合类和数组.(1)数组的长度是固定的,集合的长度是可变的.(2)数组是用来存放基本数据类型的,集 ...

  6. Java Map 集合类简介

      作者:Jack Shirazi 了解最常用的集合类型之一 Map 的基础知识以及如何针对您应用程序特有的数据优化 Map. 本文相关下载: · Jack 的 HashMap 测试 · Oracle ...

  7. Java常用集合类详解

    在Java中有一套设计优良的接口和类组成了Java集合框架,使程序员操作成批的数据或对象元素极为方便.所有的Java集合都在java.util包中. 在编写程序的过程中,使用到集合类,要根据不同的需求 ...

  8. JAVA Map集合类简介

    了解最常用的集合类型之一 Map 的基础知识以及如何针对您应用程序特有的数据优化 Map. 本文相关下载: · Jack 的 HashMap 测试· Oracle JDeveloper 10g jav ...

  9. Java之集合类

    出处:http://blog.csdn.net/zhangerqing 一.集合类简介 数组是很常用的一种的数据结构,我们用它可以满足很多的功能,但是,有时我们会遇到如下这样的问题: 1.我们需要该容 ...

随机推荐

  1. 【c++内存分布系列】单独一个类

    首先要明确类型本身是没有具体地址的,它是为了给编译器生成相应对象提供依据.只有编译器生成的对象才有明确的地址. 一.空类 形如下面的类A,类里没有任何成员变量,类的sizeof值为1. #includ ...

  2. 搞明白这八个问题,Linux系统就好学多了。

    正在犹豫入坑Linux学习的同学或者已经入坑的同学,经常会问到这样八个问题.今天,这些问题我都会一一解答,希望我的看法能帮助各位同学.常言道“好的开始是成功的一半”,如果你明白了以下八个问题,就能有一 ...

  3. 【LeetCode 213】House Robber II

    This is an extension of House Robber. After robbing those houses on that street, the thief has found ...

  4. python的Requests模块使用tips

    post方法提交的是表单,要用data放dict get方法请求的是参数,要用params放dict HTTP头部是大小写不敏感的

  5. Handling HTTP 404 Error in ASP.NET Web API

            Introduction: Building modern HTTP/RESTful/RPC services has become very easy with the new AS ...

  6. bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)

    [题意] 给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠. [思路] 首先用dijkstra算法构造以1为根的最短路树. 将一条无向边看作两条有向边,考察一条不在最短路树上 ...

  7. Python 学习笔记(三)Function

    python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量 1. Scope: • If a variable is assi ...

  8. Tkinter教程之Button篇(1)

    本文转载自:http://blog.csdn.net/jcodeer/article/details/1811298 #Tkinter教程之Button篇(1)#Button功能触发事件'''1.一个 ...

  9. LeetCode 232 Implement Queue using Stacks

    Implement the following operations of a queue using stacks. push(x) -- Push element x to the back of ...

  10. Linux下搭建jdk

    1.上oracle下载jdk-8u73-linux-x64.gz文件(其他版本的也可以,不过本教程以.gz格式为准,其他格式没有尝试过,不造怎么弄) 2.在linux桌面上右键->打开终端 3. ...