Java集合容器

mac2025-11-06  17

在编程的时,常常需要集中存放多个数据.可以使用数组来保存多个对象,但数组的长度不可变化,图图打包在初始化数组时指定了数组长度,这个数组长度就是不可变的,如果需要保存数量变化的数据,数组就有点无能为力了;而且数组无法保存具有映射关系的数。为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),Java提供了集合类/容器。 java中的集合类主要由两个派生接口 Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些字接口或实现类。 上图显示了Collection和Map体系里的集合,其中List和Set接口是Collection接口派生的两个子接口,它们分别代表了有序集合和无序集合。图中Map所有个实现类用于保存具有映射关系的数据(键值对)。Map保存的每项数据都是key-value对,就是由key和value两个值组成的键值对。

Collection和Iterator接口

Collection接口是List和Set接口的父接口,改接口定义的方法即可以用于操作Set集合,也可以用于操作List集合。

public class CollectionTest{ public static void main(String[] args){ Collection c = new ArrayList(); c.add("蜘蛛侠"); c.add(6); System.out.println("c集合的个数为:"+c.size());//输出2 c.remove("蜘蛛侠"); System.out.println("c集合的个数为:"+c.size());//输出1 System.out.println("判断c集合是不是包含蜘蛛侠:"+c.contains("蜘蛛侠"));//输出true Collection b = new HashSet(); b.add("java我的最爱"); b.add(6); c.removeAll(b);//在c中移除b中集合里的元素 c.clear//清楚c集合 b.retainAll(c);//仅保留b集合里只剩下c集合的元素 } }

上面创建了两个Collection对象,一个c集合,一个b集合,其中c是ArrayList,而b是HashSet。虽然它们使用的实现类不同,但当把它们当成Collection来使用时,使用add,clear,remove等方法来操作集合元素时没有任何区别。 Iterator接口也是java集合框架的成员,但它与Collection系列,Map系列的集合不一样,Iterator则主要用于遍历(迭代器)Collection中的元素

public class IteratrorTest{ public static void main(String[] args){ Collection b = new HashSet(); b.add("java我的最爱"); b.add(10); Iterator it = b.iterator(); while(it.hasNext){ String b1 = (String)(it.next());//Iterator返回的是Object数据所以强制转换 System.out.println(b1); if(b1.equals("10")){ it.remove();//从集合中删除上次next()方法返回的元素 } } System.out.println(b); } }

使用Iterator迭代过程中,不可修改集合元素。只能操作remo()方法删除上一次next()方法返回的结合元素才可以;否则会引发java.util.ConcurrentMondificantionException异常。 使用foreach循环遍历集合

ublic class IteratrorTest{ public static void main(String[] args){ Collection b = new HashSet(); b.add("java我的最爱"); b.add(10); for(Object ob:b){ System.out.println(ob); } } }

Set和HashSet

HashSet是Set接口的典型实例,大多数时候使用Set集合时就是使用这个实现类。HashSet按Hash算法来储存集合中的元素,因此具有很好额存取和查找性能。 HashSet具有以下特点: 1.不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。 2.HashSet不是同步的,如果多个线程同时访问一个HashSet,假设有两个或者两个以上线程同时修改了HashSet集合时,则必通过大妈来保证其同步。 3.集合元素可以是null。 当向HashSet集合中存入一个元素时,HashSet会调用该对象的HashCode()方法来得到该对象的HashCode值,然后根据HashCode值决定该对象在HashSet中的存储位置。如果有两个元素通过equals()方法比较返回true。但他们的HashCode()方法返回值不想等,HashSet将会把他们存储在不同的位置,依然可以添加成功。 也就是说,HashSet集合判断两个元素ian给的标准是两个对象通过equals()方法比较相等,并且两个对象的HashCode()方法返回值也相等。

class A{//重写equals()方法但是没有重写HashCode()方法 public boolean equals(Object obj){ return true; } } class B{//重写HashCode()方法没重写equals()方法 public int hashCode(){ return 1; } } class C{//重写HashCode()总是返回2和equals()方法总是返回true public boolean equals(Object obj){ return true; } public int hashCode(){ return 2; } } public class HashSetTest{ public static void main(String[] args){ HashSet hs = new HashSet(); hs.add(new A()); hs.add(new A()); hs.add(new B()); hs.add(new B()); hs.add(new C()); hs.add(new C()); System.out.println(hs);//输出结果是两个A 两个B 和一个C } }

所以当把一个对象放入HashSet中时,如果需要重写该对象对应类的equals()方法,则也应该重写器hashCode()方法。规则是:如果两个对象通过equals()方法比较返回true,这两个对象的hashCode值也应该相同。

TreeSet类

TreeSet可以确保集合元素处于排序状态。

public class TreeSetTest{ public static void main(String[] args){ TreeSet nums = new TreeSet(); nums.add(15); nums.add(19); nums.add(16); System.out.println(nums); } }

List集合和ListIterator

List作为Collection接口的子接口,当然可以用Collection接口里的全部方法。而且由于List是有序集合,因此List集合里增加了一些根据索引来操作集合元素的方法。具体查询API。

public class ListTest{ public static void main(String[] args){ List b = new ArrayList(); b.add(new String("java 我的最爱")); b.add(new String("dota2 我的最爱")); b.add(new String("美食 我的最爱")); b.add(0,new String("美女"));//在第一个位置插入字符串 b.remove(2);//删除第二个元素 b.set(1,new String("帅哥"));//将第二个元素替换 } }

上面一些List的一些用法。java1.8为Liset集合增加了sort()和replaceAll()两个常用的默认方法,其中rort()方法需要一个Comparator独享来控制元素排序,程序可以使用Lambda表达式来作为参数;而replaceAll()方法则需要一个UnaryOperator来替换所有集合元素,UnaryOperator也是一个函数式接口,因此程序也可使用Lambda表达式作为参数。直接调用sort()方法是默认升序的。replaceAll()替换全部。

public class SortTest{ public static void main(String[] args){ List b = new ArrayList(); b.add(6); b.add(45); b.add(89); b.sort((o1,o2)->01-02);//大小排序 System.out.println(b); } }

上面一段代码简单的介绍了List中的sort()方法是用情况。 与Set只提供了一个iterator()方法不同,List还额外提供了一个listIterator()方法,该方法返回一个ListIterator对象,ListIterator接口继承了Iterator接口,提供了专门操作List的方法。ListIterator接口在Iterator接口上增加了三个方法。拿ListIterator与普通的Iterator进行对比,不难发现ListIterator曾加了向前迭代的功能,而且ListIterator还可通过add()方法向List集合中添加元素(Iterator只能删除)。

public class ListIteratorTest{ public static void main(String[] args){ String[] str = {"你好呀","哈哈","呵呵"}; List blist = new ArrayList(); for(int i = 0;i<b.length;i++){ blist0.add(b[i]); } ListIterator it = blist.listIterator(); while(it.hasNext()){ System.out.println(it.next()); } System.out.println("========反向迭代=========="); while(it.hasPrevious()){ System.out.println(it.previous()); } } }

ArrayList和Vector 实现类

ArrayList和Vector作为List类的两个典型实现,完全支持List接口的全部功能。 ArrayList和Vector类都是基于数组实现的额List类,所以 ArrayList和Vector类封装了一个动态的,允许在分配的Object[]数组。 ArrayList和Vector对象使用initialCapacitay参数来设置该数组的长度,当向 ArrayList和Vector中添加元素超出了该数组的长度时,它们会自动扩容。 ArrayList扩容原长度的1.5倍和Vector扩容为原长度的2倍。 ArrayList和Vector用法几乎完全相同,它们最显著的区别是:ArrayList是线程不安全的,当多个线程访问同一个ArrayList集合时,如果有超过一个线程修改了ArrayList集合,则程序必须保证该集合的同步性;但Vector集合则是线程安全的,无需程序保证程序的同步性。因为Vector是线程安全的,所以Vector的形成比ArrayList的性能姚笛。

Map集合

Map用于保存具有映射关系的数据,因此Map集合力保存着两组值,一组值用与保存Map里的key,另一外一组用于保存Map里 的value,key和value都可以是任何引用类型的数据。Map的key不允许重复,既同一个Map对象的任何两个key通过equals方法比较总返回false。 key和value之间存在单项一对一的关系,既通过指定的key,总能找到唯一的确定的value。从Map中取出数据时,只要给出指定的key,就可以取出队形的value。 HashMap 底层:哈希表的结构 初始容量:16 加载因子:0.75 扩容:2倍 如果对HashMap的key是自定义的引用数据类型,需要对key的数据的类型重写equals和hashCode()方法,实现去重。value会覆盖,如果key值相同的话。想要value在key值相同的情况下不被覆盖,要先判断如果key值相同就不存储value,key值不同的时候才存储value:containsValue和containsKey方法。 与HashSet类似的是,如果使用可变对象作为HashMap、Hashtable的key,并且程序修改了作为key的可变对象,则也可能出现与HashSet类似的情形:程序再也无法准确访问到Map中被修改过的Key。

最新回复(0)