Java编程那些事儿80——荟萃框架简述
当前位置:以往代写 > JAVA 教程 >Java编程那些事儿80——荟萃框架简述
2019-06-14

Java编程那些事儿80——荟萃框架简述

Java编程那些事儿80——荟萃框架简述

副标题#e#

9.6.3 荟萃框架简述

在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要领。

对付这些荟萃类,下面凭据以上三个系列的顺序一一举办说明。


#p#副标题#e#

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要领,类内部都自动移动将被删除位置后续的所有元素向前移动,担保索引值的持续性。

#p#副标题#e#

f、set要领

Object set(int index, Object element)

该要领的浸染是修改索引值为index的内容,将本来的内容修改成工具element的内容。

g、size要领

int size()

该要领的浸染是返回当前容器中已经存储的有效元素的个数。

h、toArray要领

Object[] toArray()

该要领的浸染是将当前容器中的元素凭据顺序转换成一个Object数组。

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

#p#分页标题#e#

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类中沟通或雷同的成果要领一般是成对呈现的。

#p#副标题#e#

9.6.3.2 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

#p#副标题#e#

9.6.3.3 Map系列

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

#p#分页标题#e#

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()

该要领的浸染是返回当前日期中存储的名称:值数据的组数。

#p#副标题#e#

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

#p#副标题#e#

9.6.3.4 利用示例

如前所述,荟萃框架中的类只是提供了一种数据存储的方法,在实际利用时,可以按照逻辑的需要选择符合的荟萃类举办利用。

下面以一个字符串计较的示例演示荟萃类的实际利用。

该措施的成果为计较一个数字字符串,譬喻”1+2*31-5”、”12*30/34-450”等,的计较功效,在该示例中支持四则运算,可是不支持括号。本示例中计较的字符串要求正当。

该措施实现的道理是:首先凭据运算符作为隔断,将字符串差分为数字字符串和运算符字符串的序列,由于分拆出的字符串数量不牢靠,所以存储到List系列的Vector容器中,然后凭据运算符的优先级举办计较。

该措施的代码如下:

#p#分页标题#e#

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

9.7 总结

#p#分页标题#e#

在本章中,主要先容了java.lang包和java.util包中较量常见的类的利用,熟悉了JDK API的根基利用,把握了文档的查阅以及要领挪用等一些根基的技术,为后续章节的进修打下坚硬的基本。

    关键字:

在线提交作业