黑马程序员_java的集合一_07

来源:互联网 发布:java清除浏览器缓存 编辑:程序博客网 时间:2024/04/30 00:44

<a href="http://www.itheima.com" target="blank">android</a>

<a href="http://www.itheima.com" target="blank">java培训</a>期待与您交流


一,数据多了用对象存,对象多了用集合存储。java中的集合就是对象的一种存储方式,也可以把它们看作是容器

二,数组和集合的区别:数组是固定类型和长度的而集合只要是对象就可以,长度不固定。

三,将集合中的共性进行向上抽取形成一个体系就是:集合框架。顶层说明了其最基本的性质


四,为什么使用迭代器Iterator借口

       1, 因为每一个容器对数据的存储方式都有不同(数据结构不同)“取”这个动作具体的实现方法也不同,当“取”这个动作不足以用一个方法来表示的时候,就需要用一个对象来表示。“取”的动作很复杂,就把复杂的多个功能封装到对象里面。这个对象用一个内部类来描述,即把“取出”定义在了集合的内部(这样是为了方便的直接访问内部的元素)。每个容器都有“取”的动作,虽然具体的实现细节不同,但是都符合“先判断元素有无,在取出”这样的规则。把这样的共性的东西向上抽取就形成了Iterator<E>借口

       2,这样的好处就是:若果再有新的数据结构的集和时,只需要定义一个内部类implements Iteraror即可;内部类将具体的“取元素”的动作封装了,暴露在外面的只有规则。

五,什么是ArrayList

    ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处:

  • 动态的增加和减少元素
  • 实现了ICollection和IList接口
  • 灵活的设置数组的大小
六,ArrayList基本操作
1,构造方法
ArrayList提供了三个构造器:
public ArrayList();
默认的构造器,将会以默认(16)的大小来初始化内部的数组
public ArrayList(ICollection);
用一个ICollection对象来构造,并将该集合的元素添加到ArrayList
public ArrayList(int);
用指定的大小来初始化内部的数组,
2,常用方法

ArrayList a1=new ArrayList();

1)添加

         a1.add("java09");

         add方法的参数类型是Object。以便于接收任意类型对象。集合中存储的都是对象的引用(地址)

2)删除

         a1.remove("java09");

         a1.removeAll(a2);//删除与a2相同的元素

         a1.clear()//清空集合

3)判断。

         a1.contains("java09");

         a1.isEmpty();

4)获取长度

         a1.size();

5)获取交集。

         a1.retainAll(a2)//a1保留和a2相同的元素。

6)获取元素

方法1:迭代器

Iterator it = a1.iterator();

while(it.hasNext()){

      System.out.println(it.next());

}

方法2:高级for循环方法迭代

优点是循环完后创建的对象自动释放,而while那种是先创建对象,对象在调用完不会自动释放

for(Iteratorit = al.iterator(); it.hasNext() ){  
       System.out.println(it.next());

}   

七,ArrayList的同步属性

       IsSynchronized属性和ArrayList.Synchronized方法
IsSynchronized属性指示当前的ArrayList实例是否支持线程同步,而ArrayList.Synchronized静态方法则会返回一个ArrayList的线程同步的封装。如果使用非线程同步的实例,那么在多线程访问的时候,需要自己手动调用lock来保持线程同步,例如:
ArrayList list = new ArrayList();
//ArrayList为非线程包装的时候,SyncRoot属性其实就是它自己,但是为了满足ICollectionSyncRoot定义,这里还是使用SyncRoot来保持源代码的规范性
lock( list.SyncRoot ){
       list.Add( “Add a Item” );
}
        如果使用ArrayList.Synchronized方法返回的实例,那么就不用考虑线程同步的问题,这个实例本身就是线程安全的,实际上ArrayList内部实现了一个保证线程同步的内部类,ArrayList.Synchronized返回的就是这个类的实例,它里面的每个属性都是用了lock关键字来保证线程同步。但是,使用这个方法(ArrayList.Synchronized)并不能保证枚举的同步,例如,一个线程正在删除或添加集合项,而另一个线程同时进行枚举,这时枚举将会抛出异常。所以,在枚举的时候,你必须明确使用 SyncRoot 锁定这个集合。

八,ArrayList最佳使用建议
    这一节我们来讨论ArrayList与数组的差别,以及ArrayList的效率问题
  (1)ArrayList是Array的复杂版本
ArrayList内部封装了一个Object类型的数组,从一般的意义来说,它和数组没有本质的差别,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。
  (2)内部的Object类型的影响
         对于一般的引用类型来说,这部分的影响不是很大,但是对于值类型来说,往ArrayList里面添加和修改元素,都会引起装箱和拆箱的操作,频繁的操作可能会影响一部分效率。
但是恰恰对于大多数人,多数的应用都是使用值类型的数组。
消除这个影响是没有办法的,除非你不用它,否则就要承担一部分的效率损失,不过这部分的损失不会很大。
  (3)数组扩容
这是对ArrayList效率影响比较大的一个因素。
每当执行Add、AddRange、Insert、InsertRange等添加元素的方法,都会检查内部数组的容量是否不够了,如果是,它就会以当前容量的两倍来重新构建一个数组,将旧元素Copy到新数组中,然后丢弃旧数组,在这个临界点的扩容操作,应该来说是比较影响效率的。
     例1:比如,一个可能有200个元素的数据动态添加到一个以默认16个元素大小创建的ArrayList中,将会经过:
16*2*2*2*2 = 256
四次的扩容才会满足最终的要求,那么如果一开始就以:
ArrayList List = new ArrayList( 210 );
的方式创建ArrayList,不仅会减少4次数组创建和Copy的操作,还会减少内存使用。

     例2:预计有30个元素而创建了一个ArrayList:
ArrayList List = new ArrayList(30);
在执行过程中,加入了31个元素,那么数组会扩充到60个元素的大小,而这时候不会有新的元素再增加进来,而且有没有调用TrimSize方法,那么就有1次扩容的操作,并且浪费了29个元素大小的空间。如果这时候,用:
ArrayList List = new ArrayList(40);
那么一切都解决了。
所以说,正确的预估可能的元素,并且在适当的时候调用TrimSize方法是提高ArrayList使用效率的重要途径。
   (4)频繁的调用IndexOf、Contains等方法(Sort、BinarySearch等方法经过优化,不在此列)引起的效率损失
首先,我们要明确一点,ArrayList是动态数组,它不包括通过Key或者Value快速访问的算法,所以实际上调用IndexOf、Contains等方法是执行的简单的循环来查找元素,所以频繁的调用此类方法并不比你自己写循环并且稍作优化来的快,如果有这方面的要求,建议使用Hashtable或SortedList等键值对的集合。

    (5)一般ArrayList查询较快而CRUD较慢,LinkedList相反。

九,LinkedList简介

LinkedList类扩展AbstractSequentialList并执行List接口。它提供了一个链接列表数据结构。它具有如下的两个构造函数,说明如下
– LinkedList( )
– LinkedList(Collection c)
– 第一个构造函数建立一个空的链接列表。
– 第二个构造函数建立一个链接列表,该链接列表由类集c中的元素初始化
LinkedList类的一些方法

public boolean add(Object element) 向链表的末尾添加一个新的节点对象element
public void add(int index,Object element)向链表的指定位置尾添加一个新的节点对象element
public void addFirst(Object element)把节点对象element添加到链表的表头
public void addLast(Object element)把节点对象element添加到链表的末尾
public void cleat()删除链表的所有节点对象
public Object remove(int index)删除指定位置上的节点对象
public boolean remove(Object element)将首次出现的节点对象element删除
public Obiect removeFirst() 删除第一个节点对象,并返回这个节点对象.
public Object removeLast() 删除最后一个节点对象
public Object get(int index)得到链表中指定位置上的节点对象
public Object getFirst()得到链表中的第一个节点对象
public Object getLast()得到链表中的最后一个节点对象
public int indexOf(Object element) 返回节点对象element,在链表中首次出现的位置,如果链表中无此节点,则返回-1
public int lastIndexOf(Object element) 返回节点对象element,在链表中最后出现的位置,如果链表中无此节点,则返回-1
public Object set(int index ,Object element) 用节点对象element替换指定位置的节点对象,并返回链表中先前位置处的节点对象
public int size()返回链表的长度,即节点的个数
public boolean contains(Object element) 判断链表节点对象中是否含有element

LinkedList是采用双向循环链表实现的。

利用LinkedList实现栈(stack)、队列(queue)、双向队列(double-ended queue )。
ArrayList底层采用数组完成,而LinkedList则是以一般的双向链表(double-linked list)完成,其内每个对象除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素。如果我们经常在List的开始处增加元素,或者在List中进行插入和删除操作,我们应该
使用LinkedList,否则的话,使用ArrayList将更加快速。当执行搜索操作时,采用ArrayList 比较好。



----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------

详情请查看:http://edu.csdn.net/heima

0 0
原创粉丝点击