集合框架(1)
1、数组的特点与弊端
(1)特点:
-
- 数组初始化以后,长度就确定了。
- 数组中的添加的元素是依次紧密排列的,有序的,可以重复的。
- 数组声明的类型,就决定了进行元素初始化时的类型。不是此类型的变量,就不能添加。
- 可以存储基本数据类型值,也可以存储引用数据类型的变量
- Object []arr = new Object[10];
arr[0] = new String();
arr[1] = new Date();
(2)弊端
-
- 数组初始化以后,长度就不可变了,不便于扩展
- 数组中提供的属性和方法少,不便于进行添加、删除、插入、获取元素个数等操作,且效率不高。
- 数组存储数据的特点单一,只能存储有序的、可以重复的数据
- Java 集合框架中的类可以用于存储多个对象,还可用于保存具有映射关系的关联数组。
2、集合框架体系介绍
Java 集合可分为 Collection 和 Map 两大体系:
- Collection接口:用于存储一个一个的数据,也称单列数据集合。
- List子接口:用来存储有序的、可以重复的数据(主要用来替换数组,"动态"数组)
实现类:ArrayList(主要实现类)、LinkedList、Vector
-- Set子接口:用来存储无序的、不可重复的数据(类似于高中讲的"集合")
实现类:HashSet(主要实现类)、LinkedHashSet、TreeSet
- Map接口:用于存储具有映射关系“key-value对”的集合,即一对一对的数据,也称双列数据集合。(类似于高中的函数、映射。(x1,y1),(x2,y2) ---> y = f(x) )
- HashMap(主要实现类)、LinkedHashMap、TreeMap、Hashtable、Properties
- JDK提供的集合API位于java.util包内
3、Collection接口
- JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)去实现
- Collection 接口是 List和Set接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 集合。方法如下:
(1) 添加:add方法
@Test
public void test1(){Collection collection = new ArrayList();//add 向集合中添加元素,添加内容为Object o;collection.add("TIRENDNESS");collection.add(1314);//自动装箱,int-->Integercollection.add(new Object());collection.add(new Person("QUM",18));}
addAll方法
//addAll
collection.addAll(collection1);//将collection1中的元素全部加入方法调用者Collection中
//加入后,对比原本的size长度 collection.size() = collection.size()+collection1.size()
另外;
//collection.add(collection1);此时将集合collection1看作一个对象
//加入后collection的size为 collection.size()++;
collection.addAll(collection1);
System.out.println(collection.size());
(2)判断
<3> int size():获取当前集合中实际存储的元素个数
<4>boolean isEmpty():判断当前集合是否为空集合
<5>boolean contains(Object obj):判断当前集合中是否存在一个与obj对象equals返回true的元素,此方法调用equals方法,若在String或者包装类Integer中已经重写,则检验字面量;若尚未重写,则比较地址值。
//contains
System.out.println(collection.contains(1314));//超出128,实际上比较两个new的对象,比较字面量。
//与==不同,与重写后的equals相同
System.out.println(collection.contains(new String("Qum")));//String类中重写过equals方法
System.out.println(collection.contains(new Person("Qum",18)));//false
//Person类中没有重写equals方法,因此调用equals方法时比较对象的地址,输出false
<6>boolean containsAll(Collection coll):判断coll集合中的元素是否在当前集合中都存在。即coll集合是否是当前集合的“子集”
<7>boolean equals(Object obj):判断当前集合与obj是否相等
(3)删除
<8> void clear():清空集合元素
<9> boolean remove(Object obj) :从当前集合中删除第一个找到的与obj对象equals返回true的元素。 (需要注意对象所属的类中equals方法是否完成重写)
<10> boolean removeAll(Collection coll):从当前集合中删除所有与coll集合中相同的元素。即this = this - this ∩ coll ,删除交集
<11> boolean retainAll(Collection coll):从当前集合中删除两个集合中不同的元素,使得当前集合仅保留与coll集合中的元素相同的元素,即当前集合中仅保留两个集合的交集,即this = this ∩ coll;保留交集
@Test
public void test2(){Collection collection = new ArrayList();collection.add("TIRENDNESS");collection.add(1314);collection.add(new Object());collection.add(new Person("Qum",18));System.out.println(collection);Collection collection1 = new ArrayList();collection1.add(new String("winner") );collection1.add(521);collection1.add(1314);System.out.println(collection.size());//remove,移除指定元素collection.remove(1314);//collection.remove(new Object());//无法移除,调用equals方法时无法找到与新建对象相同的集合元素collection.remove(new Person("Qum",18));//在Person类中重写equals方法则可以移除System.out.println(collection);//removeAll,从当前集合中删除与输入集合中相同的元素collection.removeAll(collection1);//retainAll,保留交集//clearcollection1.clear();System.out.println(collection1);
}
(4)其它
<12> Object[] toArray():返回包含当前集合中所有元素的数组
<13> hashCode():获取集合对象的哈希值
<14> iterator():返回迭代器对象,用于集合遍历
@Test
public void test3(){Collection collection = new ArrayList();collection.add("TIRENDNESS");collection.add(1314);collection.add(new Object());collection.add(new Person("Qum",18));System.out.println(collection);Collection collection1 = new ArrayList();collection1.add(new String("winner") );collection1.add(521);collection1.add(1314);Object []arr = collection1.toArray();System.out.println(Arrays.toString(arr));//打印数组值}
补充:关于数组与集合之间的转换
集合--->数组 调用toArray方法;collection.toArray();.
数组--->集合 调用Arrays.asList(Object o);方法
@Test
public void test4(){String [] arr = new String[]{"AA","BB"};Collection collection = Arrays.asList(arr);System.out.println(collection);
}
注意:包装类中的Integer值将基本数据类型int包装为对象,因此下面代码中两个数组size长度不同
@Test
public void test5(){//Arrays.asList(Object o);要求传入对象值,包装类可以做到,但基础数据类型不行。Integer []arr = new Integer[]{1,2,3};//包装类,Integer的值可以视作三个对象List list = Arrays.asList(arr);System.out.println(list.size());int []arr1 = new int[]{1,2,3};//基本数据类型,只能将数组视作对象放入asList方法中。List list1= Arrays.asList(arr1);System.out.println(list1.size());
}
4. Iterator(迭代器)接口
(1) Iterator接口
- 在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.Iterator。Iterator接口也是Java集合中的一员,但它与Collection、Map接口有所不同。
- Collection接口与Map接口主要用于存储元素
- Iterator,被称为迭代器接口,本身并不提供存储对象的能力,主要用于遍历Collection中的元素
- Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
- public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的。
- 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
while (collection.iterator().hasNext()){System.out.println(iterator.next());
}//错误写法,会循环输出第一个集合元素//匿名对象只能使用一次!
- Iterator接口的常用方法如下:
- public E next():返回迭代的下一个元素。
- public boolean hasNext():如果仍有元素可以迭代,则返回 true。
- 注意:在调用it.next()方法之前必须要调用it.hasNext()进行检测。若不调用,且下一条记录无效,直接调用it.next()会抛出NoSuchElementException异常。
@Test
public void test1(){Collection collection = new ArrayList();collection.add("AA");collection.add("AA");Person p1 = new Person("Frank",24);collection.add(p1);collection.add(128);//自动装箱,int --->Intergercollection.add(new String("十二月一日,晴"));Iterator iterator = collection.iterator();//System.out.println(iterator.getClass());for (int i = 0; i <collection.size(); i++) {System.out.println(iterator.next());}//遍历输出//System.out.println(iterator.next());//如果超出集合中元素的个数,报NoSuchElementException异常//但操作中常常与hasNext搭配使用,hasNext方法检验迭代器中是否还存在没有输出的元素,并返回对应的布尔值,while (iterator.hasNext()){System.out.println(iterator.next());}}
(2)迭代器的执行原理
Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素。
首先,调用hasNext()方法判断Iteractor实例是否还存在可以输出的集合元素,若返回true,则进入while循环,调用next()方法。
一旦next()方法执行,指针下移,将下移之后指向的集合元素返回。
使用Iterator迭代器删除元素:java.util.Iterator迭代器中有一个方法:void remove() ;
注意:
- Iterator可以删除集合的元素,但是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法。
- 如果还未调用next()或在上一次调用 next() 方法之后已经调用了 remove() 方法,再调用remove()都会报IllegalStateException。
- Collection已经有remove(xx)方法了,为什么Iterator迭代器还要提供删除方法呢?因为迭代器的remove()可以按指定的条件进行删除。
(3)foreach循环
- foreach循环(也称增强for循环)是 JDK5.0 中定义的一个高级for循环,专门用来遍历数组和集合的。
- 它用于遍历Collection和数组。通常只进行遍历元素,在遍历的过程中对集合元素不进行增删操作。
- foreach循环的语法格式:
for(元素的数据类型 局部变量 : Collection集合或数组){
//操作局部变量的输出操作
}
//这里局部变量就是一个临时变量,自己命名就可以
public class ForeachTest {@Testpublic void test1(){Collection collection = new ArrayList();collection.add("TIRENDNESS");collection.add(1314);collection.add(new Object());collection.add(new Person("Qum",18));System.out.println(collection);for (Object obj : collection){//对象类型 对象名 : 需要遍历的集合/数组名System.out.println(obj);}Object[]arr = collection.toArray();for (Object obj : arr){System.out.println(obj);}}
}
关于元素的增删:for循环内部输出语句可以输出修改后的值,若在for循环外部重新遍历,输出未进行修改的值。
@Test
public void test2(){String [] arr = new String[]{"AA","BB"};for (String str : arr){str = "HIHI";System.out.println(str);}//HIHI HIHI 虽然str与数组元素的地址不同,但此循环中输出修改后的strSystem.out.println();for (String str : arr){str = "HIHI";}for (String str : arr){System.out.println(str);}//AA BB,类似于String不可变性的讲解,str与数组中的元素位于不同地址System.out.println();for (int i = 0;i<arr.length;i++){arr[i] = "HIHI";System.out.println(arr[i]);}//HIHI HIHI}