注册 登录
Office中国论坛/Access中国论坛 返回首页

ganlinlao的个人空间 http://www.office-cn.net/?230471 [收藏] [复制] [分享] [RSS]

日志

在Freebasic中使用集合类(泛型)(第一节)

已有 1794 次阅读2015-5-21 11:59 |个人分类:FreeBasic

接下来,介绍的这个库,蛮有用的,它以类似java的集合类
包装了freebasic的集合类,这样便于在实际中使用。

第一节:集合类基础概念的了解
mdTypes 是一个模仿Java 类的 FreeBASIC 的集合类。
如果这些类在java中是泛型的集合类,那么FreeBasic也允许通过宏来实现某些类型的泛型
到目前为止,MdTypes提供的集合类,包括了一系列的集合对象:list和map等
list 类:
- md/util/mdCollection(T)
-- md/util/mdList(T)
---- md/util/mdVector(T)
------ md/util/mdStack(T)
-- md/util/mdSet(T)
-- md/util/mdQueue(T)

map 类:
- md/util/mdMap(K, V) (using inner class mdMapEntry(K, V))
--- md/util/mdDictionary(K, V)
----- md/util/mdHashtable(K, V)
------- md/util/mdProperties

要遍历list类,下面这些迭代器是可用的:
- md/util/mdIterator(T)
--- md/util/mdArrayIterator(T)
- md/util/mdEnumeration(T)
对于象我这样不熟悉java或c#的人来说,有必要对list,map等一些概念进行适当了解。
******************************************
接下来的知识点是Java集合类的基础教程
*****************************************
Colleciton接口
   Collection是最基本的集合接口,一个Collection代表一组object,即Collection的元素(Elements)。一些collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java不提供直接继承自collection的类,java提供的类都是继承collection的“子接口”如List和set。     
      所有实现collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的collection,有一个collection参数的构造函数用于创建一个新的collection,这个新的collection与传入的collection有相同的元素,后一个构造函数允许用户复制一collection。
       如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:
    Iterator it = collection.iterator(); // 获得一个迭代子
    while(it.hasNext()) {
      Object obj = it.next(); // 得到下一个元素
    }
由Collection接口派生的两个接口是List和Set。
       Collection的方法:
       (1) 单元素添加、删除操作:
             boolean add(Object o):将对象添加给集合
           boolean remove(Object o): 如果集合中有与o相匹配的对象,则删除对象o
       (2) 查询操作:
            int size() :返回当前集合中元素的数量
            boolean isEmpty() :判断集合中是否有任何元素
            boolean contains(Object o) :查找集合中是否含有对象o
            Iterator iterator() :返回一个迭代器,用来访问集合中的各个元素
       (3) 组操作 :作用于元素组或整个集合
            boolean containsAll(Collection c): 查找集合中是否含有集合c 中所有元素
           boolean addAll(Collection c) : 将集合c 中所有元素添加给该集合
           void clear(): 删除集合中所有元素
           void removeAll(Collection c) : 从集合中删除集合c 中的所有元素
           void retainAll(Collection c) : 从集合中删除集合c 中不包含的元素
       (4) Collection转换为Object数组 :
            Object[] toArray() :返回一个内含集合所有元素的array
            Object[] toArray(Object[] a) :返回一个内含集合所有元素的array。运行期返回的array和参数a的型别相同,需要转换为正确型别。

2、iterator接口:
         collection接口的iterator方法返回一个iterator。iterator接口方能以迭代方式逐个访问集合中各个元素,并安全的从collection中除去适当的元素。
       (1)boolean hasNext()
           判断是否存在另一个可访问的元素
      (2)object next()
           返回要访问的下一个元素。如果到达集合结尾则抛出NoSuchElementException异常
     (3)void Remove()
       删除上次访问返回的对象。本方法必须紧跟在一个元素的访问后执行。如果上次访问后合已被修改,方法将抛出IllegalStateException。
      “Iterator中删除操作对底层Collection也有影响。”迭代器是故障快速修复(fail-fast)的。这意味着,当另一个线程修改底层集合的时候,如果您正在用 Iterator 遍历集合,那么,Iterator就会抛出 ConcurrentModificationException (另一种 RuntimeException异常)异常并立刻失败

3、List接口:
           List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。和下面要提到的Set不同,List允许有相同的元素。
      List接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。
      (1) 面向位置的操作包括插入某个元素或 Collection 的功能,还包括获取、除去或更改元素的功能。在List 中搜索元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置 :
   void add(int index, Object element):
        在指定位置index上添加元素element
   boolean addAll(int index, Collection c):
        将集合c的所有元素添加到指定位置index
   Object get(int index):
        返回List中指定位置的元素
   int indexOf(Object o):
        返回第一个出现元素o的位置,否则返回-1
   int lastIndexOf(Object o):
        返回最后一个出现元素o的位置,否则返回-1
   Object remove(int index):
        删除指定位置上的元素
   Object set(int index, Object element):
        用元素element取代位置index上的元素,并且返回旧的元素

       (2) List 接口不但以位置序列迭代的遍历整个列表,还能处理集合的子集:
  ListIterator listIterator():
       返回一个列表迭代器,用来访问列表中的元素
   ListIterator listIterator(int index):
        返回一个列表迭代器,用来从指定位置index开始访问列表中的元素
   List subList(int fromIndex, int toIndex):
       返回从指定位置fromIndex(包含)到toIndex(不包含)范围中各个元素的列表视图

   在“集合框架”中有两种常规的 List 实现:ArrayList 和 LinkedList。
使用哪一种取决于您特定的需要。如果要支持随机访问,而不必在除尾部的任何位置插入或除去元素, 那么,ArrayList 提供了可选的集合。但如果,您要频繁的从列表的中间位置添加和除去元素,而 只要顺序的访问列表元素,那么,LinkedList 实现更好。
“ArrayList 和 LinkedList 都实现 Cloneable 接口,都提供了两个构造函数,一个无参的,一个接受另一个Collection”
4.LinkedList类:
     LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
  注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
    List list = Collections.synchronizedList(new LinkedList(...));
LinkedList添加了一些处理列表两端元素的方法。
       (1)void addFirst(Object o): 将对象o添加到列表的开头
           void addLast(Object o):将对象o添加到列表的结尾
       (2)Object getFirst(): 返回列表开头的元素
           Object getLast(): 返回列表结尾的元素
       (3)Object removeFirst(): 删除并且返回列表开头的元素
           Object removeLast():删除并且返回列表结尾的元素
       (4)LinkedList(): 构建一个空的链接列表
           LinkedList(Collection c): 构建一个链接列表,并且添加集合c的所有元素 。
5.ArrayList类:
ArrayList实现了可变大小的数组。
ArrayList封装了一个动态再分配的Object[]数组。每个ArrayList对象有一个capacity。
一个capacity表示存储列表中元素的数组的容量。当元素添加到ArrayList时,它的capacity 在常量时间内自动增加。在向一个ArrayList对象添加大量元素的程序中,可使用 ensureCapacity方法增加capacity。这可以减少增加重分配的数量。
       (1) void ensureCapacity(int minCapacity):
            将ArrayList对象容量增加minCapacity
  (2) void trimToSize():
             整理ArrayList对象容量为列表当前大小。使用这个操作减少ArrayList对象存储空间。

Vector类
  Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和 ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了 Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出 ConcurrentModificationException,因此必须捕获该异常。
Stack 类
  Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

set接口:(数学中的集合)
    Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
  很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
  请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。
set接口没有引用新方法,所以set就是一个collection,只不过其行为不同。

7.Comparable接口和Comparator接口
  在“集合框架”中有两种比较接口:Comparable接口和Comparator接口。像String和Integer等Java内建类实现 Comparable接口以提供一定排序方式,但这样只能实现该接口一次。对于那些没有实现Comparable接口的类、或者自定义的类,您可以通过 Comparator接口来定义您自己的比较方式。
 Comparable接口
 在java.lang包中,Comparable接口适用于一个类有自然顺序的时候。假定对象集合是同一类型,该接口允许您把集合排序成自然顺序。
 int compareTo(Object o): 比较当前实例对象与对象o,如果位于对象o之前,返回负值,如果两个对象在排序中位置相同,则返回0,如果位于对象o后面,则返回正值

Map接口:
 请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个 value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。
(1) 添加、删除操作:
  Object put(Object key, Object value):
将互相关联的一个关键字与一个值放入该映像。如果该关键字已经存在,那么与此关键字相关的新值将取代旧值。方法返回关键字的旧值,如果关键字原先并不存在,则返回 null
   Object remove(Object key):
从映像中删除与key相关的映射
   void putAll(Map t):
将来自特定映像的所有元素添加给该映像
   void clear():
从映像中删除所有映射
 “键和值都可以为null。但是,您不能把Map作为一个键或值添加给自身。”
 (2) 查询操作:
   Object get(Object key):
          得与关键字key相关的值,并且返回与关键字key相关的对象,如果没有在该映像中找 到该关键字,则返回null
   boolean containsKey(Object key):
         判断映像中是否存在关键字key
   boolean containsValue(Object value):
        判断映像中是否存在值value
   int size():
       返回当前映像中映射的数量
   boolean isEmpty():
        判断映像中是否有任何映射
 (3) 视图操作 :处理映像中键/值对组
   Set keySet(): 返回映像中所有关键字的视图集
   Collection values():返回映像中所有值的视图集
 Set entrySet(): 返回Map.Entry对象的视图集,即映像中的关键字/值对

Hashtable类
  Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。
  添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。
Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。
使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:
    Hashtable numbers = new Hashtable();
    numbers.put(“one”, new Integer(1));
    numbers.put(“two”, new Integer(2));
    numbers.put(“three”, new Integer(3));
  要取出一个数,比如2,用相应的key:
    Integer n = (Integer)numbers.get(“two”);
    System.out.println(“two = ” + n);
  由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希表的操作。
  如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。
  Hashtable是同步的。

HashMap类
  HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap 的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。

WeakHashMap类
  WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。

总结:
 Collection 接口是一组允许重复的对象。
  • Set 接口继承 Collection,但不允许重复,使用自己内部的一个排列机制。
  • List 接口继承 Collection,允许重复,以元素安插的次序来放置元素,不会重新排列。
  • Map接口是一组成对的键-值对象,即所持有的是key-value pairs。Map中不能有重复的key。拥有自己的内部排列机制。
  容器中的元素类型都为Object。从容器取得元素时,必须把它转换成原来的类型。
        如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。  
  要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
  尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。

*****************************************************
以上内容是java集合类的基础教程
******************************************************

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

QQ|站长邮箱|小黑屋|手机版|Office中国/Access中国 ( 粤ICP备10043721号-1 )  

GMT+8, 2024-4-19 18:15 , Processed in 0.058502 second(s), 17 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

返回顶部