集合类和泛型

时间:2020-11-24 17:00:52

一、集合类

集合类和数组同是容器,有何不同?

1.数组的长度是固定的,集合类的长度不固定

2.数组存储基本类型,集合类存储对象,集合中不能存基本数据类型。

集合容器因为内部数据结构不同,有多种具体容器。

不断向上抽取,就形成了集合框架。

框架的顶层为Collection接口。

 (一)LIst

有序的Collection,此处有序是指数据存入的顺序。

特点:

1.有序,存入和取出的顺序一致

2.所有元素有角标(素引)

LIst常见的特有方法有一个共同的特点,就是可以操作角标。

List list=new ArrayList();
list.add("a1");
list.add("a2");
Iterator it=list.Iterator();
while(it.hasNext())
{
    Object obj=it.Next();
    if (obj.equals("a2"))
   {
        list.add("a3"); 
    }
}

上述代码在执行时是错误的,因为List类的迭代器在使用时容器长度是固定的,不能在迭代时修改容器的长度。

要修改上述错误,我们不能在迭代时修改容器的长度,但是我们可以修改迭代器的长度。可以使用Iterator接口的子接口ListIterator来实现。代码如下:

List list=new ArrayList();
list.add("a1");
list.add("a2");
Iterator it=list.listIterator(); //使用列表迭代器
while(it.hasNext())
{
    Object obj=it.Next();
    if (obj.equals("a2"))
   {
       it.add("a3");  //使用迭代器的插入方法
    }
}

List接口的有三种:(一般除了Vector外,都是不同步的。)

1.Vector:内部结构是数组数据结构,容量会自动调整。Vector是同步的。

2.ArrayList:内部也是数组数据结构,基本等同于Vector,但是它是不同步的,单线程中效率较高。查询的速度快。

3.LinkedList:内部是链表数据结构,是不同步的,增删速度非常快。

(二)Set

特点:

1.所有元素不重复

2.没有顺序

 主要有两种结构:

1.HashSet:无重复,无顺序

判断两个对象是否相同,先判断两个对象的HashCode,如相同,再判断equals,如相同,则两个对象相同。如HashCode不相同,则无须再判断equals。

2.TreeSet:无重复,有顺序

(三)Map

Collection一次添加一个元素,Map一次添加一对元素。所以Map也叫双列集合,Map集合中存储的是键值对。一个映射中不能包含重复的键,每个键只能对应一个值。也就是说Map必须保证键的唯一性。

1.Map添加:

  value put(key,value):返回前一个和key关联的值,如果没有,返回null

2.删除

void clear():清空map集合

value remove(key):根据指定的key翻出对应的键值对

3.判断

boolean containsKey(key);

boolean containsValue(value);

boolean isEmpty();

4.获取

value get(key):通过键获取值,如果没有该键,返回null。当然可以通过返回null,来判断是否包含指定键。

int size(); 获取键值对的个数

 Map集合没有迭代器。通过Map转成set就可以迭代。找到了另一个方法entrySet。该方法将键和值的映射关系作为对象存储到了set集合中,而这个映射关系的类型就是Map.Entry类型。

Set<Map.Entry<Integer,String>> entrySet=map.entrySet();
Iterator<Map.Entry<Integer,String>> it=entrySet.iterator();
while (it.hasNext())
{
     Map.Entry<Integer,String> me=it.next();
    Integer key=me.getKey();
    String value=me.getValue();
    System.out.println(key+":"+value);
}

 Map常用的子类:

1.Hasthtable:内部结构是哈希表,是同步的,不允许null作为键和null作为值

     有一个子类:properties,用来存储键值对型的配置文件的信息。经常和IO技术相结合。

2.HashMap:内部结构是哈希表,是不同步的,允许null作为键和null作为值

3.TreeMap:内部结构是二叉树,是不同步的,可以对Map集合中的键进行排序。

 二、泛型

在JDK1.5以后出现。

好处:

  1.将运行时期的问题ClassCastException转到了编译时期。

  2.避免了强制转换的麻烦。

<>:什么时候用?当操作的引用数据类型不确定的时候,就使用<>。将要操作的引用数据类型引入即可。其实<>就是一个用于接收具体引用数据类型的参数范围。

运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。

定义一个泛型类:

pulbic class Tool<w>

{

    ……

}

也可以定义一个泛型接口

interface Inter<T>

{

   public void show(T t)

  { }

}

 可以将泛型定义在方法上:

public <w> void show(w str)

{

     ……

}

当方法静态时,不能访问类上定义的泛型,如果静态方法使用泛型,只能将泛型定义在方法上。

public static <w> void show(w str)

{

    ……

}

在使用泛型参数时,如果有多种泛型,可使用如下代码:

public void show(Tool<?> t)

{

     Iterator <?> it=t.iterator();  

  ……

}

或用如下代码:

public <T> void show(Tool<T> t)

{

     Iterator <T> it=t.iterator();  

  ……

}

泛型通配符还可以进行限定,如向上限定(一般用于存储数据):

public static void show(Tool<? extends Person> str)

{

    ……

}

也可向下限定(一般用于读取数据):

public static void show(Tool<? super Person> str)

{

    ……

}

最后,集合的一些技巧:

需要唯一吗?

需要:Set

   需要制定顺序:

                 需要:TreeSet

                不需要:HashSet

不需要:List

       需要频繁增删吗?

                需要:LinkedList

                不需要:ArrayList

Array——数组、查询快、有角标

Link——链表、增删快、add/get/remove/first/lash等方法

Hash——哈希表、唯一性,有时需要覆盖hashCode和equals方法

Tree——二叉树、排序,两个接口:Comparable和Comparator

三、集合工具

1. Collections

    里面的方法都是静态的。比如排序:

public static void  show()
{
    List<String> list=new ArrayList<String>();
    list.add("abcde");
    list.add("cba");
    list.add("aa");
    list.add("zzz");
    Collections.sort(list);
    System.out.println(list);
}

  比如交换值:

   Collections.swap(list,i,j);

 对集合中的位置进行随机

  Collections.shuffle(list);

给非同步的集合加锁,可以使用Collections.synchronizedCollection(Collection<T> c),其原理如下 :

List list=new ArrayList(); //非同步
list=MyCollections.synList(list); //返回一个同步的list


class MyCollections
{
   public List synList(List list)
   {
       return new MyList(list);
   }

   private class MyList implements List
   {
       private List list;
       private static final Object lock=new Object();
       MyList(List list)
       {
           this.list=list;
       }

       public boolean add(Object obj)
       {
           synchronized(lock)
           {
               return list.add(obj);
           }
       }

       public boolean remove(Object obj)
       {
           synchronized(lock)
           {
               return list.remove(obj);
           }
       }
   }

}

2.Arrays

将数组转成集合

int [] arr={31,11,51,61};

List<int []> list=Arrays.asList(arr);

将集合转数组

List <String> list=new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
/*toArray需要传定一个指定类型的数组,如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同的size的数组,如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位默认为null
*/
string[] arr=list.toArray(new String[2]);
System.out.println(Arrays.toString(arr));

 注意,导入静态名称空间时,要用

import static java.util.Collections.sort;