Java学习之集合

时间:2022-03-18 13:40:25

 

Collection:集合层次中的根接口,JDK没有提供这个接口直接的实现类。

Set:不能包含重复的元素。SortedSet是一个按照升序排列元素的Set

List:是一个有序的集合,可以包含重复的元素。提供了按索引访问的方式。

Map:包含了key-value对。Map不能包含重复的keySortedMap是一个按照升序排列keyMap


一般将数据结构分为两大类:线性数据结构和非线性数据结构。线性数据结构有线性表、栈、队列、串、数组和文件;非线性数据结构有树和图。

线性表的逻辑结构是n个数据元素的有限序列:(a1, a2 ,a3,…an)

n为线性表的长度(n0)n=0的表称为空表。

数据元素呈线性关系。必存在唯一的称为第一个的数据元素;必存在唯一的称为最后一个的数据元素;除第一个元素外,每个元素都有且只有一个前驱元素; 除最后一个元素外,每个元素都有且只有一个后继元素。

所有数据元素在同一个线性表中必须是相同的数据类型。

 

线性表按其存储结构可分为顺序表和链表。用顺序存储结构存储的线性表称为顺序表;用链式存储结构存储的线性表称为链表

将线性表中的数据元素依次存放在某个存储区域中,所形成的表称为顺序表一维数组就是用顺序方式存储的线性表。

 

(Stack)也是一种特殊的线性表,是一种后进先出(LIFO)的结构。

栈是限定仅在表尾进行插入和删除运算的线性表,表尾称为栈顶(top),表头称为栈底(bottom)

栈的物理存储可以用顺序存储结构,也可以用链式存储结构。

 

队列(Queue)是限定所有的插入只能在表的一端进行,而所有的删除都在表的另一端进行的线性表。

表中允许插入的一端称为队尾(Rear),允许删除的一端称为队头(Front)

队列的操作是按先进先出(FIFO)的原则进行的。

队列的物理存储可以用顺序存储结构,也可以用链式存储结构。

 

散列表又称为哈希表。散列表算法的基本思想是:以结点的关键字为自变量,通过一定的函数关系(散列函数)计算出对应的函数值,以这个值作为该结点存储在散列表中的地址。

当散列表中的元素存放太满,就必须进行再散列,将产生一个新的散列表,所有元素存放到新的散列表中,原先的散列表将被删除。在Java语言中,通过负载因子(load factor)来决定何时对散列表进行再散列。例如:如果负载因子是0.75,当散列表中已经有75%的位置已经放满,那么将进行再散列。

负载因子越高(越接近1.0),内存的使用效率越高,元素的寻找时间越长。负载因子越低(越接近0.0),元素的寻找时间越短,内存浪费越多。

HashSet类的缺省负载因子是0.75

 

package com.source;

 

import java.io.FileInputStream;

import java.util.*;

 

 

public class CollectionTest {

   

    public static void PrintElements(Collection c){ //使用Iterator迭代器输出集合的内容

       Iterator it=c.iterator();                 //Collection c用于向上转型

       while(it.hasNext()){

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

       }

    }

 

     

    public static void main(String args[]){

       System.out.println("-------------------------ArrayList-------------------------");

       //ArrayList的随机访问元素的效率非常高

       ArrayList al=new ArrayList();

       al.add(new Family(4,"laoda"));

       al.add(new Family(3,"laoer"));

       al.add(new Family(3,"laosan"));

       al.add(new Family(1,"laosi"));

      

      

       System.out.println("列表数组“");

       Object[] o=al.toArray();

       for(int i=0;i<o.length;i++){

           System.out.print(o[i]+"");

       }

      

       System.out.println();

       System.out.println();

       System.out.println("数组列表“");

       List l=Arrays.asList(al);

        PrintElements(l);

      

       System.out.println();

       System.out.println("Iterator迭代器输出");

       Collections.sort(al,new Family.FamilyComparator());

       /*实现了Comparable接口的数组列表,可以通过 Collections.sort(List<T> list)方法来进行自动排序

         也可以通过Collections.sort(List<T> list, Comparator<? super T> c)增加一个比较器参数来

         定义排序规则

       */

       //newFamily.FamilyComparator()  加载Family的比较器 

       //Collections.reverseOrder()  实现倒序排列

       PrintElements(al);                              

      

      

       System.out.println("-------------------------LinkedList-------------------------");

       //可以实现数据结构的栈,双向循环链表等结构,适用于高效的增加删除元素

       LinkedList ll=new LinkedList();

       System.out.println("构造一个栈,栈:后进先出,先进后出 栈竖形排列 上边为栈顶 下边为栈底");

       ll.addFirst(1);

       ll.addFirst(2);

       ll.addFirst(3);

       ll.addFirst(4);

       ll.addFirst(5);

       PrintElements(ll); //依然使用迭代器输出 也可以sysout直接打印输出 会变为横向数组[4, 3, 2, 1]

       System.out.println("删除栈顶元素"+ll.removeFirst());

       PrintElements(ll);

       System.out.println("查看当前栈顶元素"+ll.getFirst());

      

      

       System.out.println("-------------------------HashSet-------------------------");

       HashSet hs=new HashSet(); //Hashset 称为哈希表 也叫散列表 需要实现hashcode()equals()方法

       hs.add(new Family(4,"laoda"));

       hs.add(new Family(3,"laoer"));

       hs.add(new Family(3,"laosan"));

       hs.add(new Family(1,"laosi"));

       hs.add(new Family(1,"laosi"));

       PrintElements(hs);  

      

      

       System.out.println("-------------------------TreeSet-------------------------");

       TreeSet ts=new TreeSet(new Family.FamilyComparator());  //类似于ArrayList

       ts.add(new Family(4,"laoda"));                       //也需要比较器来比较元素大小

       ts.add(new Family(3,"laoer"));                      

        ts.add(new Family(3,"laosan"));

       ts.add(new Family(1,"laosi"));

       ts.add(new Family(1,"laosi"));

       PrintElements(ts);  

       //Hastset实现了哈希算法优于TreeSetTreeSet用于元素比较,且set中不能存放相同元素

      

      

       System.out.println("-------------------------HashMap-------------------------");

       HashMap hm=new HashMap();

       hm.put(1, "laoda");

       hm.put(2, "laoer");

       hm.put(3, "laosan");

       hm.put(4, "laosi");

       System.out.println(hm.get(1)+" "+hm.get(2)+" "+hm.get(3)+" "+hm.get(4));

       System.out.println();

       System.out.println("HashMapkeySet()方法返回一个Set类型的键的集合");

       Set keys=hm.keySet();

       PrintElements(keys);

      

       System.out.println();

       System.out.println("HashMapValues()方法返回一个Collection类型的值的集合");

       Collection values=hm.values();

       PrintElements(values);

      

       System.out.println();

       System.out.println("HashMapentrySet()方法返回一个Map.Entry类型的键值对的集合");

       Set entrySet=hm.entrySet();

       Iterator it=entrySet.iterator();

       while(it.hasNext()){ 

           System.out.println(it.next()); //可以直接用迭代器输出内容

       }

       while(it.hasNext()){ 

           Map.Entry me=(Map.Entry)it.next();  //也可以用迭代器把结果赋值给Map.Entry类型的对象

           System.out.println(me.getKey()+":"+me.getValue());//通过此对象在获取值

           System.out.println(me.hashCode());

       }

       //HashMap的速度通常比TreeMap快,TreeMap用于元素比较,只有在需要排序的时候才用TreeMap

      

      

       System.out.println("-------------------------Properties-------------------------");

       System.out.println("使用Properties返回当前java配置的系统属性");

       Properties pp=System.getProperties(); 

       pp.list(System.out);

      

       System.out.println();

       System.out.println("使用Properties集合来读取后缀名为.ini的配置文件");

       Properties pp2=new Properties();

       try{

           pp2.load(new FileInputStream("E:/J2EE/Java Workspace/Test/com/source/Properties.ini"));  //加载文件

       }//读取文件需要使用绝对路径

       catch(Exception e){

           e.printStackTrace();

       }

       Enumeration e=pp2.propertyNames();//获取文件的信息,传给一个枚举类型的对象

       while(e.hasMoreElements()){

           /*需要为中文字符转码 使用JDK/bin目录下的native2ascii.exe程序

             例如Collection=/u96c6/u5408

                ArrayList=/u6570/u7ec4/u5217/u8868

                Set=/u7ec4/u5408

                Map=/u6620/u5c04*/

           String key=(String)e.nextElement();//获取ini文件中的键的值

           String value=(String)pp2.getProperty(key);//根据键来获取值

           System.out.println(key+"="+value);//输出ini文件中的结果

       }

    }

}

class Family implements Comparable{//实现Comparable接口,对实现它的每个类的对象进行整体排序

    int num;

    String name;

    public Family(int num,String name){

       this.num=num;

       this.name=name;

    }

    public int compareTo(Object o) {//Comparable的实现方法,可以自定义排序规则

       Family f=(Family)o;

       return num>f.num ? 1 : (num==f.num) ? 0 : -1;

    }

    public String toString(){

       return num+" "+name;

    }

    static class FamilyComparator implements Comparator {//实现一个比较器接口Comparator

       public int compare(Object o1,Object o2){//Comparator的实现方法 用于比较两个对象

           Family f1=(Family) o1;

           Family f2=(Family) o2;

           int result=f1.num>f2.num ? 1 : (f1.num==f2.num ? 0 : -1);

           if(result==0)

              return f1.name.compareTo(f2.name);

           return result;

          

       }

    }

    public int hascode(){

       return num*name.hashCode();

    }

    public boolean equals(Object o){

       Family f=(Family)o;

       return name==f.name && name.equals(f.name);

      

    }

   

}