java的集合框架

1, java类集的整个体系的组成和关系,以及各个接口,类的文字说明:

集合框架的特征:高性能,对动态数组,链接表,树和散列表的实现是高性能,允许不同类型的类集以相同的方式工作.它不受对象数组长度的限制

Collection:

  -|:List  里面的内容是有序的(存入和取出的顺序一致),允许重复的内容,有索引,它扩充了Collection接口,拥有更多的方法

     --|:ArrayList  内部是数组数据结构,查询速度快,不同步,判断元素是否存在,删除元素,底层用的是equals方法

     --|:LinkedList  内部是链表数据结构,增删的速度快,也是不同步的

  -|:Set  不能存放重复的内容,是无序的,

    --|:HashSet  不能存放重复的元素,采用散列的储存方式,没有顺序,判断元素是否存在,删除元素,底层用的是equals和hashcode方法

    --|:TreeSet   不能存放重复的元素,输出的数据是有序的

------------------------------------------------------------------------------------------------------------------

名称 数据结构 是否有序 是否同步(安全) 特点
ArrayList 数组 有序 不同步 按照索引查询速度快
LinkedList 链表 有序 不同步 增删速度快
Vector 数组 有序 同步 线程安全,按照索引查询速度快
TreeSet 二叉树 无序(可以提供比较器) 不同步 根据比较器自定义排序
HashSet 哈希表 无序 不同步 按照内容查询速度快

-------------------------------------------------------------------------------------------------------------------

package cn.wjd.ArrayList;
import java.util.ArrayList;
import java.util.Iterator;
import cn.wjd.bean.Person;
public class ArrayListTest {
    public static void main(String[] args) {
        ArrayList a1 = new ArrayList();
        a1.add(new Person("zhangsan1",21));//存自定义对象的时候,需要强转
        a1.add(new Person("zhangsan2",22));
        a1.add(new Person("zhangsan3",23));
        a1.add(new Person("zhangsan4",24));
        Iterator it = a1.iterator();
        while (it.hasNext()) {
//            System.out.println(((Person) it.next()).getName()); 这段代码具有局限性,在循环中,一个对象调用2次方法,会出现异常
            Person p = (Person) it.next();//解决方法,得到一个对象,然后使用对象进行调用方法
            System.out.println(p.getName() +"-->" + p.getAge());
        }
    }
}

以上ArrayList代码中,两个注意点,我这边在ArrayList的容器中,加入的是自定义的对象,所以在输出数据的时候,一定要进行强制转换,强转得到对象,输出对象内容,这两个步骤一定要分开走,否则假如是一步走的话在while循环的输出会出现异常.

由以上代码,引出集合的标准输出的方法,Iterator(迭代输出,使用最多的输出方式)和ListIterator(专门用于输出List中的内容).

2, 在ArrayList的集合中去掉重复的元素,同理还有另外一个需求,去掉一个数组中重复的元素,请看下面的代码

去掉集合中的重复元素

package cn.arraylist;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ArrayList02 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("c");
        List<String> li = getSingleElement(list);
        System.out.println(li);
    }

    public static List<String> getSingleElement(List<String> list) {
        ArrayList<String> temp = new ArrayList<String>();
        ListIterator<String> it = list.listIterator();
        while(it.hasNext()){
            String str = it.next();
            if(!temp.contains(str))
                temp.add(str);
        }
        return temp;
    }

}

去掉数组中的重复元素

package cn.demo;

import java.util.ArrayList;
import java.util.List;



//数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
public class Demo2 {
    public static void main(String[] args) {
        int[] arr = {4,2,4,6,1,2,4,7,8};
        List<Integer> list = new ArrayList<Integer>();
        for(int i : arr){
            if(!list.contains(i))
                list.add(i);
        }
        System.out.print(list);

其实上面两段代码,使用到的思路是一样的,给定一个集合或者数组的时候,我们要改变它的长度,这个肯定是要考虑到用集合去解决的,因为数据的长度是不可以改变的,所以都得定义一个集合变量,来存储最后不重复的元素.

在去掉数组中重复元素的话,还有一个更加牛逼的方法,先将数组遍历装到ArrayList集合中(就算是int型的数组,它会自动变成Integer),然后把ArrayList这个数组中的元素全部添加到HashSet集合中去,由于HashSet的特点,所以直接去掉了重复元素,不过最后打印的数据的排列顺序会有点变化.你懂的.

package cn.demo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;

//数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
public class Demo01 {
    public static void main(String[] args) {
        int[] arr = {4,2,4,6,1,2,4,7,8};
        List<Integer> al = new ArrayList<Integer>();
        for(int i : arr){
            al.add(i);
        }
        
        Set<Integer> set = new HashSet<Integer>();
        set.addAll(al);
        System.out.println(set);
    }
}

迭代输出:Iterator(迭代含义:一个个对集合中的内容进行判断,有内容就将其取出)

最标准的做法,只要碰到集合输出,一定要想到这个接口.标准输出代码如下:

Iterator it = col.iterator();  //Collection中的方法,返回Iterator对象
while(it.hasNext()){           //Iterator对象进行迭代判断,是否有下一个值
    System.out.println(it.next());// 挨个取出当前元素
}

 

双向迭代输出:ListIterator(List专用的,只能通过List接口实例化,只能输出List接口中的内容)

package cn.wjd.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class ListDemo02 {
    public static void main(String[] args) {
        List list = new ArrayList();
        //show(list);
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        System.out.println("原来的-->" + list);
        ListIterator it = list.listIterator();  //获取列表迭代器对象,它在迭代的过程中,可以完成对元素的增删改查,这个是list集合特有的
        while (it.hasNext()) {       //使用列表迭代器,操作的对象是迭代器对象,不是集合对象  
            Object obj = it.next();   
            if(obj.equals("abc2"))
                it.add("abc4");
            else                 
                System.out.println("next -->" + obj);
                
        }
        System.out.println("列表迭代器迭代之后的-->" + list);
        
    /*    list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Object obj = it.next();   //java.util.ConcurrentModificationException
            if(obj.equals("abc2"))//在进行迭代操作的时候,不能进行集合的操作,这样容易出现异常,如,迭代的话知道集合的元素个数,
                list.add("abc4");//再进行集合操作,元素个数会发现变化,这样就出现了异常
            else                 //解决方法,使用ListIterator接口来完成
                System.out.println("next -->" + obj);
                
        }*/
    }
    public static void show(List list) {
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");
        Iterator it = list.iterator();
        while (it.hasNext()) {
            System.out.println("next-->" + it.next());
        }
        //List中特有的取数的方法,get()方法
        for (int i = 0; i < list.size(); i++) {
            System.out.println("get-->" + list.get(i));
        }
    }
}

先看API中List接口中一个特殊的方法:2

在List中,有了该方法,它就存在一个特有的取数方式,利用for循环,循环次数为List集合对象的长度,然后通过该方法循环输出.

List集合只能使用ListIterator进行输出的原因(ConcurrentModificationException 异常出现的原因):我们在进行迭代操作的时候,如果集合的引用和迭代器对象同时来操作容器中的内容,通过集合获取到的对应的迭代器,然后对集合进行增删改查的操作,假如使用之前的Iterator迭代的话,这个接口中是没有增删改查的方法的,这个时候我们只能使用它的子接口ListIterator来完成输出,直接查阅API中ListIterator的内容就了然了.

------------------------------------------------------------------------------------------------------------------------------------------------

Set下面的小弟TreeSet它是如何实现有序排放的?

1:让元素具有自己的比较功能,实现Comparator接口,通过覆盖其compare(T o1,T o2)比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数的方法,来自己建立2个对象比较的准则

int compare(T o1,T o2)比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。

package cn.wjd.treeset;
import java.util.Iterator;
import java.util.TreeSet;
import cn.wjd.bean.Person;
public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new ComparatorByName());//构造方法中直接传入已经定义好的比较器对象
        ts.add(new Person("zhangsan",22));
        ts.add(new Person("zhangsan",21));
        ts.add(new Person("bhangsan4",24));
        ts.add(new Person("a3",22));
        ts.add(new Person("dhangsan5",25));
        Iterator it = ts.iterator();
        while (it.hasNext()) {
            Person p = (Person)it.next();
            System.out.println(p.getName() + "-->" + p.getAge());
        }
    }
package cn.wjd.treeset;
import java.util.Comparator;
import cn.wjd.bean.Person;
public class ComparatorByName implements Comparator {
    public int compare(Object o1, Object o2) {
        Person p1 = (Person)o1;
        Person p2 = (Person)o2;
        int temp = p1.getName().compareTo(p2.getName());//compareTo是String类中的方法,按照字典的顺序比较2个字符串
        return temp == 0?p1.getAge() - p2.getAge():temp;
    }//该自定义的比较器中,优先比较的是Person对象的姓名,然后再比较的是Person对象的年龄

}

小插曲,关于三目运算符的格式:表达式1?表达式2:表达式3;  当表达式1是true的时候,执行表达式2,false时,执行表达式3.

一般表达式1是关系运算符或者是逻辑运算符.

2,让元素自身据有比较的功能,定义类的时候,直接让它实现Comparable接口,同时复写它的compare(T o)方法

package cn.wjd.bean;

public class Person implements Comparable {
    private String name;
    private int age;
    
    @Override
    public boolean equals(Object obj) {
        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age == p.age ;
    }
    @Override
    public int hashCode() {
        
        return name.hashCode() + age;
    }
    
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    public int compareTo(Object o) {
        Person p = (Person)o;
//        int temp = this.age - p.age;
//        return temp == 0?this.name.compareTo(p.name):temp;
        int temp = this.name.compareTo(p.name);
        return temp == 0?this.age - p.age:temp;
        /*if(this.age > p.age)
            return 1;
        if(this.age < p.age)
            return -1;
        return 0;*/
    }
    
}

一般第一种方法灵活,在开发中,第一种使用的比较多

 

HashSet

它的底层数据结构是哈希表,线程不同步,无序,高效.

如何确定该集合中元素的唯一性?
                 是通过对象的hashcode和equals方法来完成对象的唯一性
                 如果对象的hashcode值不同,就不需要判断equals方法
                 如果对象的hashcode值相同,则需要判断equals方法,记住hashcode是第一步,equals是第二部
                 true,视为相同元素,false,视为不同元素
                 记住,元素要存储在HashSet中,必须要覆盖hashcode和equals方法

关于java中的哈希表

1,对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值

2,哈希值就是这个元素的位置。

3,如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础 +1顺延。

4,存储哈希值的结构,我们称为哈希表。

5,既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。

----------------------------------------------------------------------------------------------------------------------------------------------

Map集合

Map集合中存储的是一对元素(key->value),key和value都有对应的映射关系,要保证Map集合中key的唯一性.

Map常用的子类
   --|Hashtable:内部结构哈希表,是同步的。不允许null作为键,作为值
      --|Properties类:用来存储键值对型配置文件的信息,可以和IO技术相结合
   --|HashMap:内部结构是哈希表,不是同步的。允许null作为键,作为值
   --|TreeMap:内部结构是二叉树,不同步,可以对Map中的键进行排序

Map.Entry接口简介

Map.Entry接口是Map内部定义的一个接口,专门用来保存key->value的内容,直白一点,在Map集合中插入的就是一个Map.Entry的实例化对象

----------------------------------------------------------------------------------------------------------------------------------------

集合 数据类型 是否有序 是否重复 key允许null
HashMap 哈希表 无序 不允许重复 最多一个
TreeMap 二叉树

有序

不允许重复 不允许
Hashtable 哈斯表 无序 不允许重复 最多一个

----------------------------------------------------------------------------------------------------------------------------------------

Map集合的输出方式:

由于Map它没有自己的迭代器,所以在输出的时候,需要转化成Set集合,然后再进行迭代输出.

方式1  23

方式2 12

package cn.wjd.map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MapDemo {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<Integer, String>();
        //method(map);
        method_2(map);
    }
    
    public static void method_2(Map<Integer, String> map) {
        map.put(2, "zhangsan2");
        map.put(1, "zhangsan1");
        map.put(3, "zhangsan3");
        map.put(6, "zhangsan6");
        map.put(5, "zhangsan5");
        /*Map集合第一种取出方式
         * 对Map集合进行输出,因为Map集合没有迭代器
         * 1,通过Map集合中的keySet方法,来返回Map集合中的key元素的Set集合
         * 2,使用Set集合中的迭代,对Map中的key进行迭代输出
         * 3,使用Map中的get(key)方法,来取出Map中的所有元素内容
         */
        /*Set<Integer> keyset = map.keySet();
        Iterator<Integer> it = keyset.iterator();
        while (it.hasNext()) {
            Integer key = it.next();
            String value = map.get(key);
            System.out.println(key + "-->" + value);
            
        }*/
    /*
     * Map集合的第二种取出方法
     * 也是通过Map转换成Set,进行迭代取出
     * 使用Map中的entrySet方法,来返回包含映射关系的Set视图
     * 再使用Map.EntrySet接口中的getKey和getValue方法,来取出Map中的元素
     */
        
        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();
            System.out.println(me.getKey() +"-->" +me.getValue());
            
        }
        
    }
    public static void method(Map<Integer,String> map){
        System.out.println(map.put(8, "zhangsan"));
        System.out.println(map.put(8, "lisi"));
        System.out.println(map);
    }
}
posted @ 2014-07-30 21:50  木有杂念  阅读(257)  评论(0编辑  收藏  举报