数组是保存一组对象的最有效的方式,如果你想保存一组基本类型数据,也推荐这样方式,但是数据具有固定的尺寸,而在更一般的情况中,你在程序时并不知道将需要多少个对象,或者是否需要更复杂的方式来存储对象,因此数组尺寸固定显得过于受限了。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
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
下面看一段代码:
上面我们利用ArrayList容器类来盛放Collection1对象,如果要从容器中取出对象,只有上面的两种方式么?当然不是,还记得Object类中的toString()方法吧,通过重写该方法,也可以打印出我们想要的结果。下面介绍另一种:
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)方法,那就好办啊!
咦?怎么打印结果没有变化啊?不是删除了么?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"))中添加的对象,在堆中是两片不同的内存区域,所以是不同的对象,当然不会删除!那么没有办法删除了么,当然不是,我们可以通过对象引用的方式来删除:
简单的修改Test.java:
打印结果无序,而且不会出现重复对象,其中如何判断放入的是不是同一对象也是用equals(Object o)来实现。
简单的修改Test.java:
上述put(K key, V value)中,第二个参数是Integer类型,但是直接写int类型数字,无错误,这是Java自动打包解包缘由:
自动将基础类型转换为对象
自动将对象转换为基础类型
本文中没有提及LinkedList类,和Interface Queue及其子类,因为后续有文章提及Java中的算法数据结构,当然java封装了其中的算法,通过查阅API文档,可以很好地掌握。
文中如有错误之处,请读者指正 !
下图是简单的容器分类图:(下图来自《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 Map
Type 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() + " ");
}
*/ - }
- }
点击(此处)折叠或打开
- 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() + " ");
- }
- }
- }
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() + " ");
- }
- }
- }
点击(此处)折叠或打开
- 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() + " ");
- }
- }
- }
简单的修改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"));
- }
- }
自动将基础类型转换为对象
自动将对象转换为基础类型
本文中没有提及LinkedList类,和Interface Queue及其子类,因为后续有文章提及Java中的算法数据结构,当然java封装了其中的算法,通过查阅API文档,可以很好地掌握。
文中如有错误之处,请读者指正 !