容器

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

数组是保存一组对象的最有效的方式,如果你想保存一组基本类型数据,也推荐这样方式,但是数据具有固定的尺寸,而在更一般的情况中,你在程序时并不知道将需要多少个对象,或者是否需要更复杂的方式来存储对象,因此数组尺寸固定显得过于受限了。java实用类库提供了一套想当完整的容器类来解决这个问题,其中基本的类型是List,Set,Queue和Map。

下图是简单的容器分类图:(下图来自《thinking in java》第十一章)

为了更加直观的记忆,简化上图:

java容器大致分为继承Collection接口和继承Map接口两大类。继承自Collection接口的容器,又分为Set,List接口:

1.Interface List

Type Parameters:

E - the type of elements in this list

是Collection的子接口,实现了List接口的容器类中的元素是有序的,且可以重复

List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素

JDK提供的实现List接口的容器类有AbstractList, AbstractSequentialList, ArrayList, AttributeList, CopyOnWriteArrayList, LinkedList, RoleList, RoleUnresolvedList, Stack, Vector

2.Interface Set

Type Parameters:

E - the type of elements maintained by this set

是Collection的子接口,实现了Set接口的容器类的元素是无序的,但是不可以重复,JDK提供的实现了Set接口容器类有AbstractSet, ConcurrentHashMap.KeySetView, ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, JobStateReasons, LinkedHashSet, TreeSet

Interface MapType Parameters: K - the type of keys maintained by this map V - the type of mapped values实现Map接口的类用来存储键-值对

Map接口的实现类有HashMap和TreeMap等

Map类中存储的键-值对通过键来标识,所以键值不能重复

jdk提供实现Map容器类有:AbstractMap, Attributes, AuthPRovider, ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap, Hashtable,IdentityHashMap, LinkedHashMap, PrinterStateReasons, Properties, Provider, RenderingHints, SimpleBindings,TabularDataSupport, TreeMap, UIDefaults, WeakHashMap

具体可以参考官方API,有详细的说明。http://docs.Oracle.com/javase/8/docs/api/index.html

下面看一段代码:

点击(此处)折叠或打开

public class Collection1 { private int i; private String name; public Collection1(int i,String name) { // TODO 自动生成的构造函数存根 this.i = i; this.name = name; } public int geti(){ return i; } public String getName(){ return name; } public String toString(){ return i + "-" +name +" "; }}public class Test { public static void main(String[] args){ ArrayList<Collection1> c = new ArrayList<Collection1>(); c.add(new Collection1(1, "diy")); c.add(new Collection1(2,"os")); c.add(new Collection1(3, "Lios")); for(int i=0;i<c.size();i++){ System.out.print(c.get(i).geti() + " "); } /* for(Collection1 cc :c){

System.out.print(cc.geti() + " ");

}

*/ }}

上面我们利用ArrayList容器类来盛放Collection1对象,如果要从容器中取出对象,只有上面的两种方式么?当然不是,还记得Object类中的toString()方法吧,通过重写该方法,也可以打印出我们想要的结果。下面介绍另一种:

点击(此处)折叠或打开

public class Test { public static void main(String[] args){ ArrayList<Collection1> c = new ArrayList<Collection1>(); c.add(new Collection1(1, "diy")); c.add(new Collection1(2,"os")); c.add(new Collection1(3, "Lios")); Iterator<Collection1> ite = c.iterator(); //ArrayList类中实现iterator()方法,作用:Returns an iterator over the elements in this list in proper sequence.

while(ite.hasNext()){ Collection1 t = ite.next(); System.out.print(t.geti() + " "); } } }

Iterator是什么?那么查下API先:

Interface Iterator

Type Parameters:

E - the type of elements returned by this iterator

原来它是接口,下面简单的介绍下:

Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作

Iterator接口定义了以下的方法:

default void :forEachRemaining(Consumer action)

Performs the given action for each remaining element until all elements have been processed or the action throws an exception.

boolean hasNext():判断游标右边是否有元素

E next():返回游标右边的元素并将游标移动到下一个位置

default void remove():删除游标左面的元素在执行完next之后该操作只能执行一次

原来它是为了方便对容器内元素更好地遍历操作!关于更详细的内容,请读者参考API.

如果想删除容器中的元素怎么办呢,查看api文档发现,提供我们remove(Object o)方法,那就好办啊!

点击(此处)折叠或打开

public class Test { public static void main(String[] args){ ArrayList<Collection1> c = new ArrayList<Collection1>(); c.add(new Collection1(1, "diy")); c.add(new Collection1(2,"os")); c.add(new Collection1(3, "Lios")); c.remove(new Collection1(1,"diy")); Iterator<Collection1> ite = c.iterator(); while(ite.hasNext()){ Collection1 t = ite.next(); System.out.print(t.geti() + " "); } }}

咦?怎么打印结果没有变化啊?不是删除了么?c.remove(new Collection1(1,"diy"));我想有些朋友会这样疑问,其实在调用remove()时,系统会调用equals(Object o),如果容器中要删除的对象this,和remove(Object o)函数的参数o相等的话,equals()返回true,否则返回false。对于自定义类型,那么需要重写equals()方法和hashCode()方法,两个equals的对象,那么它们的hashcode也是相等的。上述中remove(new Collection1(1,"diy")),传入的Collection1的对象,和add(new Collection1(1,"diy"))中添加的对象,在堆中是两片不同的内存区域,所以是不同的对象,当然不会删除!那么没有办法删除了么,当然不是,我们可以通过对象引用的方式来删除:

点击(此处)折叠或打开

public class Test { public static void main(String[] args){ ArrayList<Collection1> c = new ArrayList<Collection1>(); Collection1 diy = new Collection1(1, "diy"); c.add(diy); c.add(new Collection1(2,"os")); c.add(new Collection1(3, "Lios")); c.remove(diy); Iterator<Collection1> ite = c.iterator(); while(ite.hasNext()){ Collection1 t = ite.next(); System.out.print(t.geti() + " "); } }}

简单的修改Test.java:

点击(此处)折叠或打开

public class Test { public static void main(String[] args){ HashSet<Collection1> c = new HashSet<Collection1>(); Collection1 ss = new Collection1(1,"diy"); c.add(ss); c.add(new Collection1(2, "os")); c.add(new Collection1(3, "Lios")); c.add(ss); Iterator<Collection1> ite = c.iterator(); while(ite.hasNext()){ Collection1 t = ite.next(); System.out.print(t.geti() + " "); } }}

打印结果无序,而且不会出现重复对象,其中如何判断放入的是不是同一对象也是用equals(Object o)来实现。

简单的修改Test.java:

点击(此处)折叠或打开

public class Test { public static void main(String[] args){ HashMap<String, Integer> A = new HashMap<String, Integer>(); A.put("One", 1); A.put("Two", 2); A.put("Three", 3); System.out.println(A.get("One"));}}

上述put(K key, V value)中,第二个参数是Integer类型,但是直接写int类型数字,无错误,这是Java自动打包解包缘由:

自动将基础类型转换为对象

自动将对象转换为基础类型

本文中没有提及LinkedList类,和Interface Queue及其子类,因为后续有文章提及Java中的算法数据结构,当然java封装了其中的算法,通过查阅API文档,可以很好地掌握。

文中如有错误之处,请读者指正 !

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航