Java集合类初步了解

集合概述:
集合按照其存储结构可以分为两大类,即单列集合Collection和双列集合Map,这两集合的特点具体如下。

Colleetion; 单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是List和Set。其中,List的特点是元素有序、元素可重复。Set的特点是元素无序并且不可重复。List 接口的主要实现类有ArrayList和LinkedList,Set接口的主要实现类有HashSet和TreeSet;

Map: 双列集合类的根接口,用于存储具有健(Key)、值(Value)映射关系的元素,每个元素都包含一对键值,在使用Map集合时可以通过指定的Key 找到对应的Value,例如根据一个学生的学号就可以找到对应的学生。Map接口的主要实现类有HashMap和TreeMap;

Collection是所有单列集合的父接口,List接口继承自Collection接口,习惯将实现了List接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存人顺序和取出顺序一致。

ArrayList是List 接口的一个实现类,它是程序中最常见的一种集合。在ArrayList内部封装了一个长度可变的数组对象,当存人的元素超过数组长度时,ArrayList会在内存中分配一个更大的数组来存储这些元素,因此可以将ArrayList集合看作一个长度可变的数组。

ArrayList集合中大部分方法都是从父类Collection和List继承过来的,其中add()方法和get()方法用于实现元素的存取,如例所示。

package Example;
import java.util.*;
public class example01 {
	public static void main(String[] args) {
		ArrayList list = new ArrayList();//创建ArrayList集合
		list.add("stul");
		list.add("stu2");
		list.add("stu3");
		list.add("stu4");
		System.out.println("集合的长度:"+list.size());
		System.out.println("第二个元素是:"+list.get(1));
	}
}

由于ArrayList集合的底层是使用一个数组来保存元素,在增加或删除指定位置的元素时,会导致创建新的数组,效率比较低,因此不适合做大量的增删操作。但这种数组的结构允许程序通过索引的方式来访问元素,因此使用ArrayList集合查找元素很便捷。
注意:在编译例题时,会得到警告,意思是说在使用ArayList集合时并没有显示指定集合中存储什么类型的元素,会产生安全隐惠,这涉及到泛型安全机制的问题。
LinkedList集合:
克服ArrayList集合增删元素时效率低的局限性;

package Example;
import java.util.*;
public class example02 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        LinkedList link = new LinkedList();//创建LinkedList集合
        link.add("stu1");
        link.add("stu2");
        link.add("stu3");
        link.add("stu4");
        System.out.println(link.toString());//取出并打印该集合中的元素
        link.add(3,"Student");//向该集合中指定位置插入元素
        link.addFirst("First");//向该集合第一个位置插入元素
        System.out.println(link);
        System.out.println(link.getFirst());//取出该集合中第一个元素
        link.remove(3);//移除该集合中指定位置的元素
        link.removeFirst();//移除该集合中第一个元素
        System.out.println(link);
	}
}

由此可见,使用LinkedList对元素进行增删操作是非常便捷的;

Iterator接口:
在程序开发中.经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口Iterator。 Iterator 接口也是Java集合框架中的一员,但它与Collection、 Map接口有所不同.Collection接口与Map接口主要用于存储元素,而Iterator 主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

package Example;
import java.util.*;
public class example03 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub40-
        ArrayList list = new ArrayList();//创建ArrayList集合
        list.add("data_1");//向该集合中添加字符串
        list.add("data_2");
        list.add("data_3");
        list.add("data_4");
        Iterator it =list.iterator();//获取Iterator对象
        while(it.hasNext()) {      //判断ArrayList集合中是否存在下一个元
        	Object obj = it.next();//取出ArrayList集合中的元素
        	System.out.println(obj);
        }
	}
}

虽然Iterator可以用来遍历集合中的元素,但写法上比较烦琐,为了简化书写,从JDK5.0开始,提供了foreach 循环。foreach 循环是一种更加简洁的for循环,也称增强for循环。foreach循环用于遍历数组或集合中的元素,其具体语法格式如下:

for(容器中元素类型临时变量:容器变量) (
执行语句
}

package Example;
import java.util.*;
public class example04 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        ArrayList list = new ArrayList();//创建ArrayList集合
        list.add("Jack");//向ArrayList集合中添加字符串元素
        list.add("Rose");
        list.add("Tom");
        for(Object obj:list) {       //使用foreach循环遍历ArrayList对象
        	System.out.println(obj);//取出并打印ArrayList集合中的元素
        }
	}
}

①foreach循环虽然书写起来很简洁,但在使用时也存在一定的局限性。当使用foreach循环遍历集合和数组时,只能访问集合中的元素,不能对其中的元素进行修改。接下来以一个String类型的数组为例来进行演示,如例所示。

package Example;
public class example05 {
    static String[] strs= {"aaa","bbb","ccc"};
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        //foreach循环遍历数组
		for(String str:strs) {
			str="ddd";
		}
		System.out.println("foreach循环修改后的数组:"+strs[0]+","+strs[1]+","+strs[2]);
		//for循环遍历数组
		for(int i=0;i<strs.length;i++) {
			strs[i]="ddd";
		}
		System.out.println("普通for循环修改后的数组:"+strs[0]+","+strs[1]+","+strs[2]);
	}
}

②在使用Iterator 迭代器对集合中的元素进行迭代时,如果调用了集合对象的remove()方法去删除元素,会出现异常。接下来通过一个案例来演示这种异常。假设在一个集合中存储了学校所有学生的姓名,由于一个名为Annie的学生中途转学,这时就需要在选代集合时找出该元素并将其删除,具体代码如例所示。

package Example;
import java.util.*;
public class example06 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        ArrayList list = new ArrayList();//创建ArrayList集合
        list.add("Jack");
        list.add("Annie");
        list.add("Rose");
        list.add("Tom");
        Iterator it = list.iterator(); //获得Iterator对象
        while(it.hasNext()) {          //判断该集合是否有下一个元素
        	Object obj = it.next();    //获取该集合中的元素
        	if("Annie".equals(obj)) {  //判断该集合中的元素是否为Annie
        		list.remove(obj);//删除该集合中的元素
        		//解决问题
        		//break;1》只需找到该学生后跳出循环不再迭代即可;
        		//it.remove();2》调用迭代器本身的删除方法
        	}
        }
        System.out.println(list);   
	}
}

Listtlterator接口:
ListIterator迭代器是Iterator的子类;使用案例:

package Example;
import java.util.*;
public class example07 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        ArrayList<String> list = new ArrayList();//创建ArrayList集合
        list.add("data_1");
        list.add("data_2");
        list.add("data_3");
        System.out.println(list);
        ListIterator it = list.listIterator(list.size());//获得ListIterator对象
        while(it.hasPrevious()) {      //判断该对象是否有上一个元素
        	Object obj = it.previous();//迭代该对象的上一个元素
        	System.out.println(obj+" ");
        }
	}
}

注意:ListIterator迭代器只能用于List集合;
Enumeration接口:
在JDK1. 2以前还没有Iterator接口的时候,遍历集合需要使用Enumeration接口,它的用法和Iterator类似。由于很多程序中依然在使用Enumeration.因此了解该接口的用法是很有必要的。JDK中提供了一个Vector集合,该集合是List接口的一个实现类,用法与ArrayList 完全相同.区别在于Vector集合是线程安全的,面ArrayList集合是线程不安全的。在Vector类中提供了一个elements()方法用于返回Enumeration对象,通过Enumeration 对象就可以遍历该集合中的元素。接下来通过一个示例来演示如何使用Enumeration 对象遍历Vecor集合.

package Example;
import java.util.*;
public class example08 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Vector v = new Vector();//创建Vector对象
        v.add("Jack");
        v.add("Rose");
        v.add("Tom");
        Enumeration en = v.elements();//获得Enumeration对象
        /*该过程与Iterator迭代的过程类似,通过hasMoreElements()方法循环判断是否存在下一个元素,如果存在
                      * 则通过nextElement()方法逐一取出每个元素
         */
        while(en.hasMoreElements()) {     //判断该对象是否有更多元素
        	Object obj = en.nextElement();//取出该对象的下一个元素 
        	System.out.println(obj);
        }
	}
}

Set接口简介:
Set接口和 List接口一样.同样继承自Collection接口,,它与Collection接口中的方法基本一致,并没有对 Clleteo接口进行功能上的扩充,只是比Collection接口更加产格了。与List接口不同的是,Set接口中元素无序.并且都会以某种规则保证存人的元素不出现重复。

Set接口主要有两个实现类,分别是HashSet和TreeSet。其中.HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。TreeSet则是以二叉树的方式来存储元素,它可以实现对集合中的元素进行排序。
例1:

package Example;

import java.util.*;

public class example09 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        HashSet set = new HashSet();//创建HashSet集合
        set.add("Jack");//向Set集合中添加字符串
        set.add("Eve");
        set.add("Rose");
        set.add("Rose");//向该集合中添加重复元素
        Iterator it = set.iterator();//获取Iterator对象
        while(it.hasNext()) {      //通过while循环,判断集合中是否有元素
        	Object obj = it.next();//如果有元素,就通过迭代器的next()方法获取元素
        	System.out.println(obj);
        }
	}

}

例2:

package Example;
import java.util.*;
class Student{
	private String id;
	private String name;
	public Student(String id,String name) { //创建构造方法
		this.id = id;
		this.name = name;
	}
	//重写toString()方法
	public String toString(){  
		return id+":"+name;
	}
	//重写hashCode方法
	public int hashCode() {
		return id.hashCode();//返回id属性的哈希值
	}
	//重写equals方法
	public boolean equals(Object obj) {
		if(this==obj) {  //判断是否是同一个对象
			return true; //如果是,直接返回true
		}
		if(!(obj instanceof Student)) { //判断对象是否为Student类型
			return false;//如果对象不是Student类型,返回false
		}
		Student stu = (Student) obj;//将对象强制转换为Student类型
		boolean b = this.id.equals(stu.id);//判断id值是否相同
		return b;
	}
}
public class example10 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        HashSet hs = new HashSet();//创建HashSet集合
        Student stu1 = new Student("1","Jack");//创建Student对象
        Student stu2 = new Student("2","Rose");
        Student stu3 = new Student("2","Rose");
        hs.add(stu1);
        hs.add(stu2);
        hs.add(stu3);
        System.out.println(hs);
	}
}

根据前面的分析不难看出,当向集合中存人元素时,为了保证HashSet正常工作,要求在存人对象时,重写该类中的hashCode()和equals()方法。例中将字符串存人HashSet时,Sring类已经重写了hashCode()和equals()方法。但是如果将Student对象存入HashSet,结果如何?
在例2中,向HashSet集合存人三个Student对象、并将这三个对象迭代输出。运行结果中出现了两个相同的学生信息“2:Rose",这样的学生信息应该被视为重复元素,不允许同时出现在HashSet集合中。之所以没有去掉这样的重复元素是因为在定义Student 类时没有重写hashCode()和equals()方法。
上述程序例二已修改;

TreeSet集合:
TreeSet是Set接口的另一个实现类,它内部采用自平衡的排序二叉树来存储元素,这样的结构可以保证TreeSet集合中没有重复的元素,并且可以对元素进行排序。例:

package Example;
import java.util.*;
public class example11 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        TreeSet ts = new TreeSet();//创建TreeSet集合
        ts.add("Jack");//向TreeSet集合中添加元素
        ts.add("Helena");
        ts.add("Helena");
        ts.add("Eve");
        Iterator it = ts.iterator();//获取Iterator对象
        while(it.hasNext()) {
        	System.out.println(it.next());
        }
	}
}

集合中的元素在进行比较时,都会调用compareTo()方法,该方法是Comparable接口中定义的,因此要想对集合中的元素进行排序,就必须实现Comparable接口。JDK中大部分的类都实现Comparable接口,拥有了接口中的CompareTo()方法,如Integer、Double和String等。在TreeSet集合中存放Student类型对象时,如果Student类没有实现Comparable接口,则Student类型的对象将不能进行比较,这时,TreeSet集合就不知道按照什么排序规则对Student对象进行排序,最终导致程序报错。因此,为了在TreeSet 集合中存放Student对象,必须使Student类实现Comparable接口,如例所示。

package Example;
import java.util.*;
class Student implements Comparable{//定义Student类实现Comparable接口
	String name;
	int age;
	public Student(String name,int age) {//创建构造方法
		this.name = name;
		this.age = age;
	}
	public String toString() {//重写Object类的toString()方法,返回描述信息
		return name+":"+age;
	}
	public int compareTo(Object obj) {
		Student s = (Student) obj;//将比较的对象强制转化为Student类型
		if(this.age - s.age>0) {//定义比较方式
			return 1;
		}
		if(this.age - s.age == 0) {
			return this.name.compareTo(s.name);//将比较结果返回
		}
		return -1;
	}
}
public class example12 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TreeSet ts = new TreeSet();//创建TreeSet集合
        ts.add(new Student("Jack",19));//向集合中添加元素
        ts.add(new Student("Rose",18));
        ts.add(new Student("Tom",19));
        ts.add(new Student("Rose",18));
        Iterator it = ts.iterator();//获取Iterator对象
        while(it.hasNext()) {
        	System.out.println(it.next());
        }
	}
}

有时候,定义的类没有实现Comparable接口或者实现了Comparable 接口而不想按照定义的compareTo()方法进行排序。例如,希望字符串可以按照长度来进行排序,这时,可以通过自定义比较器的方式对TreeSet集合中的元素排序,即实现Comparator接口,在创建TreeSet集合时指定比较器。接下来通过一个案例来演示TreeSet集合中字符串按照长度进行排序,如例所示:

package Example;
import java.util.*;
class MyComparator implements Comparator{ //定义比较方法实现Comparator接口
	public int compare(Object obj1,Object obj2) {//定义比较方法
		String s1 = (String) obj1;
		String s2 = (String) obj2;
		int temp = s1.length()-s2.length();
		return temp;
	}
}
public class example13 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        TreeSet ts = new TreeSet(new MyComparator());
        //创建TreeSet对象时传入自定义比较器
        ts.add("Jack");//向该Set对象中添加字符串
        ts.add("Helena");
        ts.add("Eve");
        Iterator it=ts.iterator();//获取Iterator对象
        //通过while循环,逐渐将集合中的元素打印出来
        while(it.hasNext()) {
        	//如果Iterator有元素进行迭代,则获取元素并进行打印
        	Object obj=it.next();
        	System.out.println(obj);
        }
	}
}

Map接口:
Map接口是一种双列集合,它的每个元素都包含一个键对象Key和一个值对象Value, 键和值对象之间存在一种对应关系,称为映射。从Map集合中访问元素时,只要指定了Key,就能找到对应的Value。
HashMap集合是Map接口的一个实现类,它用于存储键值映射关系,但必须保证不出现重复的键。例:

package Example;
import java.util.*;
public class example03 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Map map=new HashMap();//创建Map对象
        map.put("1", "Jack");//存储键和值
        map.put("2", "Rouse");
        map.put("3", "Lucy");
        map.put("3", "Mary");//键相同,值覆盖
        System.out.println("1:"+map.get("1"));//根据键获取值
        System.out.println("2:"+map.get("2"));
        System.out.println("3:"+map.get("3"));
	}
}

程序开发中经常需要取出Map中所有的键和值,如何遍历Map中的键值对?

package Example;
import java.util.*;
public class example04 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Map map=new HashMap();//创建Map对象
        map.put("1", "Jack");//存储键和值
        map.put("2", "Rouse");
        map.put("3", "Lucy");
        /*第一种遍历Map的方式:首先调用Map对象的keySet()方法,获得存储Map中所有键的Set集合,然后通过Iterator迭代Set集合的每一个元素
                        * 即每一个键,最后通过调用get(String key)方法,根据键获取对应的值;
         */
        Set keySet=map.keySet();//获取键的集合
        Iterator it = keySet.iterator();//迭代键的集合
        while(it.hasNext()) {
        	Object key=it.next();
        	Object value = map.get(key);//获取每个键所对应的值
        	System.out.println(key+":"+value);
        }
	}
}
package Example;
import java.util.*;
public class example05 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Map map = new HashMap();//创建Map集合
        map.put("1", "Jack");//存储键和值
        map.put("2", "Rose");
        map.put("3","Lucy");
        /*第二种遍历Map的方式:首先调用Map对象的entrySet()方法获得存储在Map中所有映射的Set集合,这个集合中存放了Map,Entry类型的
                       * 元素(Entry是Map接口内部类),每个Map.Entry对象代表Map中的一个键值对,然后迭代Set集合,获得每一个映射对象,并分别调用映射
                       *对象的getKey()和getValue()方法获取键和值;·
         */
        Set entrySet=map.entrySet();
        Iterator it = entrySet.iterator();//获取Iterator对象
        while(it.hasNext()) {
        	Map.Entry entry = (Map.Entry)(it.next());//获取集合中键值对映射关系
        	Object key = entry.getKey();//获取Entry中的键
        	Object value = entry.getValue();//获取Entry中的 值
        	System.out.println(key+":"+value);
        }
	}
}
package Example;
import java.util.*;
public class example06 {
/*Map中提供了一个values()方法,通过这个方法可以直接获取Map中存储所有值的Collection集合;
 * 从运行结果可以看出HashMap集合迭代出来的元素的顺序和存入的顺序不一致。
 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Map map = new HashMap();//创建Map集合
        map.put("1","Jack");//存储键和值
        map.put("2","Rose");
        map.put("3","Lucy");
        Collection values = map.values();
        Iterator it = values.iterator();
        while(it.hasNext()) {
        	Object value = it.next();
        	System.out.println(value);
        }
	}
}
package Example;
import java.util.*;
public class example07 {
//如果想让HashMap集合迭代出来的元素的顺序和存入顺序一致,使用LinkedHashMap类,它是HashMap的子类;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Map map = new HashMap();//创建Map集合
        map.put("1","Jack");//存储键和值
        map.put("2","Rose");
        map.put("3","Lucy");
        Set keySet=map.keySet();
        Iterator it = keySet.iterator();
        while(it.hasNext()) {
        	Object key = it.next();
        	Object value = map.get(key);//获取每个键所对应的值
        	System.out.println(key+":"+value);
        }
	}
}

TreeMap集合:
用来存储键值映射关系,其中不允许出现重复的键;在TreeMap中是通过二叉树的原理来保证键的唯一性;

package Example;
import java.util.*;
public class example01 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TreeMap tm = new TreeMap();
		tm.put("1","Jack");
		tm.put("2","Rose");
		tm.put("3","Lucy");
		Set keySet = tm.keySet();//获取键的集合
		Iterator it = keySet.iterator();//获取Iterator对象
		while(it.hasNext()) {  //判断是否存在下一个元素
			Object key = it.next();//取出元素
			Object value = tm.get(key);//根据获取的键找到对应的值
			System.out.println(key+":"+value);
		}
	}
}
package Example;
import java.util.*;
/*使用TreeMap集合时,通过自定义比较器的方式对所有的键进行排序;
 * 下面定义了比较器MyComparator针对String类型的id进行比较,在实现compare()方法时,调用了String对象的compareTo()方法;由于
 * 方法中返回的是“id2.compareTo(id1)”,所以输出结果中的id按照与字典顺序相反的顺序进行排序;
 */

public class example02 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        TreeMap tm = new TreeMap(new MyComparator());//传入一个自定义比较器
		tm.put("1","Jack");//向集合中存入学生的学号和姓名
		tm.put("2","Rose");
		tm.put("3","Lucy");
		Set keySet = tm.keySet();//获取键的集合
		Iterator it = keySet.iterator();//获取Iterator对象
		while(it.hasNext()) {  //判断是否存在下一个元素
			Object key = it.next();//取出元素
			Object value = tm.get(key);//根据获取的键找到对应的值
			System.out.println(key+":"+value);
		}
	}
}
class MyComparator implements Comparator{ //自定义比较器
	public int compare(Object obj1,Object obj2) { //实现比较方法
		String id1=(String) obj1; //将Object类型的参数强转为String类型
		String id2=(String) obj2;
		return id2.compareTo(id1);//将比较之后的值返回
	}
}

Properties集合:
Map接口中的一个实现类Hashtable,与HashMap的区别:Hashtable是线程安全的。Hashtable存取元素时速度很慢,目前基本上被HashMap类所取代,但Hashtable 类有一个子类Properties在实际应用中非常重要,Propertiesz主要用来存储字符串类型的键和值,在实际开发中,经常使用Properties集合来存取应用的配置项。假设有一个文本编辑工具,要求默认背景色是红色,字体大小为14px,语言为中文,其配置项应该如下:
Backgroup-color = red
Front-Size = 14px
Language = chinese
通过Prorpertites集合对这些配置项进行存取:

package Example;
import java.util.*;
public class example03 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Properties p = new Properties();//创建Properties对象
        p.setProperty("backgroup-color", "red");
        p.setProperty("Font-size", "14px");
        p.setProperty("Language", "chinese");
        Enumeration names = p.propertyNames();//获取Enumeration对象所有键的枚举
		while(names.hasMoreElements()) { //循环遍历所有的键
        	String key = (String) names.nextElement();
        	String value = p.getProperty(key);//获取对应键的值
        	System.out.println(key+"="+value);
        }
	}   
}

Properties类中,针对字符串的存取提供了两个专用的方法setProperty()和getProperty()。setProperty()方法用于将配置项的键和值添加到Properties集
合当中。在第8行代码中通过调用Properties 的propertyNames()方法得到一个包含所有键的Enumeration对象,然后在遍历所有的键时,通过调用getProperty()方法获得键所对应的值;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值