您的位置:首页 > 编程语言 > Java开发

java基础学习集合学习笔记

2015-08-19 23:40 393 查看


------- android培训java培训、期待与您交流! ----------

集合

(1)集合的由来和特点

  A:由来

   java中描述数据的最基本单位就是类,为了方便对多个对象进行存储和遍历,

   java提供了一种新的存储数据的容器,叫集合类。

  B:特点

   长度可以变化。

   只能存储对象。

(2)集合和数组的区别

  A:集合

   只能存储对象

   长度可以变化

  B:数组

   可以存储基本数据类型,也可以存储对象类型

   长度固定

(3)集合体系的由来

  由于每个集合类的数据结构不同,所以,集合会有很多的子类。

  但是,这些子类不断的向上抽取共性内容,最终形成了集合体系。

  一个体系的学习和使用方式:

   学习顶层:顶层定义的是这个体系的共性内容。

   使用底层:底层才是具体的存在的实现类。

一、Collection接口中的常见操作

   添加元素:

    boolean add(Object obj)

   删除元素:

    void clear()

    boolean remove(Object obj)

   判断元素:

    boolean isEmpty()

    boolean contains(Object obj)

   长度:

    int size()

   迭代器:

    Iterator iterator()

 

  A:存储字符串

   //创建集合对象

   Collection c = new ArrayList();

   //创建元素对象

   String s1 = "haha";

   String s2 = "hehe";

   String s3 = "xixi";

   //把元素对象添加到集合对象中

   c.add(s1);

   c.add(s2);

   c.add(s3);

   }


二、迭代

1、概述

        迭代是取出集合中元素的一种方式。

        对于集合的元素取出这个动作:

        当不足以用一个函数来描述,需要用多个功能来体现,所以就将取出这个动作封装成一个对象来描述。就把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内部的元素。那么取出方式就被定义成了内部类。

        而每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都具有共性内容: 判断和取出。那么就可以将这些共性抽取。

         那么这些内部类都符合一个规则(或者说都抽取出来一个规则)。该规则就是Iterator。通过一个对外提供的方法:iterator();,来获取集合的取出对象。

         因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。

 

2、迭代的常见操作

        hasNext();//有下一个元素,返回真

        next();//取出下一个元素

        remove();//移除

注:在迭代时循环中next调用一次,就要hasNext判断一次。

使用:

         ArrayList a=newArrayList();//创建一个集合

        Iteratorit=a.iterator();//获取一个迭代器,用于取出集合中的元素。

        第一种打印方式:

                for(Iterator iter = a.iterator();iter.hasNext();  )

                {

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

                }

       第二种打印方式:

                 Iteratoriter = a.iterator();

                while(iter.hasNext())

               {

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

               }

3、迭代注意事项
迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。
迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。
迭代器的next方法返回值类型是Object,所以要记得类型转换。

             List   集合

(1)掌握如下体系结构图

  List 元素有序,可重复。

   |--ArrayList

    底层数据结构是数组,查询快,增删慢。

    线程不安全,效率高。

   |--Vector

    底层数据结构是数组,查询快,增删慢。

    线程安全,效率低。

   |--LinkedList

    底层数据结构是链表,查询慢,增删快。

    线程不安全,效率高。

(2)List的特有功能

  A:添加元素

   add(int index,Object obj)

  B:删除元素

   remove(int index)

  C:获取元素

   get(int index)

  D:列表迭代器

   ListIterator listIterator()

  E:修改元素

   set(int index,Object obj)

  ArrayList  集合

案例:

   **存储遍历字符串

   //创建集合对象

   List list = new ArrayList();

   //创建元素对象

   String s1 = "haha";

   String s2 = "hehe";

   String s3 = "xixi";

   //把元素对象添加到集合对象中

   list.add(s1);

   list.add(s2);

   list.add(s3);

   通过迭代器遍历集合元素

   Iterator it = list.iterator();

   while(it.hasNext())

   {

    String s = (String) it.next();

    System.out.println(s);

   }

ListIterator

1、概述 

        ListIterator是List集合特有的迭代器,是Iterator的子接口。

       在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以在迭代器时,只能用迭代器的方法操作元素。可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作。如果想要其他的操作,如添加、修改等,就需要使用其子接口:ListIterrator。该接口只能通过List集合的ListIterator方法获取。

2、ListIterator特有的方法

        add(obj);//增加

        set(obj);//修改为obj

        hasPrevious();//判断前面有没有元素

        previous();//取前一个元素

   **存储遍历自定义对象(Student已经存在,name和age)

  

   List list = new ArrayList();

   Student s1 = new Student("唐三角",20);

   Student s2 = new Student("孙悟空",25);

   Student s3 = new Student("猪八戒",22);

   list.add(s1);

   list.add(s2);

   list.add(s3);

   //遍历

   Iterator it = list.iterator();

   while(it.hasNext())

   {

    Student s = (Student)it.next();

    System.out.println(s.getName()+"***"+s.getAge());

   }

   for(int x=0; x<list.size(); x++)

   {

    Student s = (Student) list.get(x);

    System.out.println(s.getName()+"***"+s.getAge());

   }

(3)List体系下的这个三个集合类用哪一个比较好:

  A:如果是要求查询快,就使用ArrayList

  B:如果是要求增删多比较多,就使用LinkedList

  C:如果涉及多线程安全问题,就使用Vector

(4)注意:ArrayList的contains方法底层依赖的是equals方法。


枚举Enumeration

枚举:

        就是Vector特有的取出方式。Vector有三种取出方式。

        其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。

特有方法:

         addElement(obj);//添加元素,相当于add(obj);

         Enumerationelements();//Vector特有取出方式(枚举)

         hasMoreElements();//相当于Iterator的hasNext()方法

         nextElements();//相当于Iterator的next()方法

例:

Vector v=new Vector();
for(Enumeration e=v.elements();e.hasMoreElements();)

{
System.out.println(e.nextElements());

}  

LinkedList

        LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。

特有方法:

1、增

        addFirst();

        addLast();

2、获取

        //获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException

        getFirst();

        getLast();

3、删

        //获取元素,并删除元素。如果集合中没有元素,会出现NoSuchElementException

        removeFirst();

        removeLast();

在JDK1.6以后,出现了替代方法。

1、增

        offFirst();

        offLast();

2、获取

        //获取元素,但是不删除。如果集合中没有元素,会返回null。

        peekFirst();

        peekLast();

3、删

        //获取元素,并删除元素。如果集合中没有元素,会返回null。

        pollFirst();

        pollLast();

Set  集合

HasSet

        HashSet:线程不安全,存取速度快。

       可以通过元素的两个方法,hashCode和equals来完成保证元素唯一性。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals。

注意:HashSet对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。

示例:

  public class Student

  {

   private String name;

   private int age;

   public Student(){}

   public Student(String name,int age)

   {

    this.name = name;

    this.age = age;

   }

   //get/set...

   public int hashCode()

   {

    return this.name.hashCode()+this.age*11;

   }

   public boolean equlas(Object obj)

   {

    if(this==obj)

    {

     return true;

    }

    if(!(obj instanceof Student))

    {

     return false;

    }

    Student s = (Student)obj;

    return this.name.equals(s.name) && this.age==s.age;

   }

  }

  public class HashSetDemo

  {

   public static void main(String[] args)

   {

    HashSet<Student> hs = new HashSet<Student>();

    Student s1 = new Student();

    Student s2 = new Student();

    Student s3 = new Student();

    hs.add(s1);

    hs.add(s2);

    hs.add(s3);

    //遍历

   }

  }

TreeSet

1、特点

        a、底层的数据结构为二叉树结构

        b)可对Set集合中的元素进行排序,是因为:TreeSet类实现了Comparable接口,该接口强制让增加到集合中的对象进行了比较,需要复写compareTo方法,才能让对象按指定需求(如人的年龄大小比较等)进行排序,并加入集合。

        java中的很多类都具备比较性,其实就是实现了Comparable接口。

注意:排序时,当主要条件相同时,按次要条件排序。

Tree排序的两种方式

        1)第一种排序方式:自然排序

        让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也被称为元素的自然顺序,或者叫做默认顺序。

示例:

import java.util.*;

//学生类

class Student implements Comparable

{
private String name;
private int age;
Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}

public int getAge()
{
return age;
}
//复写hashCode以便HashSet集合调用
public int hashCode()
{
return name.hashCode()+age;
}
//复写equals以便HashSet集合和集合中一些比较方法调用
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new RuntimeException();
Student s = (Student)obj;
return this.name.equals(s.name)&&this.age==s.age;
}
//复写compareTo以便TreeSet集合调用
public int compareTo(Object obj)
{
Student s=(Student)obj;
if(this.age==s.age)
return this.name.compareTo(s.name);
return this.age-s.age;
//return new Integer(this.age).compareTo(new Integer(s.age)); 
}

}

class  TreeSetTest

{
public static void main(String[] args) 
{
TreeSet<Student> t=new TreeSet<Student>();
t.add(new Student("wo1",12));
t.add(new Student("wosj",2));
t.add(new Student("wo1sdj",12));
t.add(new Student("wo6sd",12));
t.add(new Student("wo",22));

for (Iterator<Student> it=t.iterator(); it.hasNext(); )
{
Student s=it.next();
System.out.println(s.getName()+"....."+s.getAge());
}
}

}

        2)第二种方式:比较器

                   当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。

                  在集合初始化时,就有了比较方式。定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

                  比较器构造方式:定义一个类,实现Comparator接口,覆盖compare方法。

                   当两种排序都存在时,以比较器为主。

示例:
/*

需求:

往TreeSet集合中存储自定义对象学生。

想按照学生的年龄进行排序。

*/

import java.util.*;

//学生类

class Student implements Comparable

{
private String name;
private int age;
Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}

public int getAge()
{
return age;
}
//复写hashCode以便HashSet集合调用
public int hashCode()
{
return name.hashCode()+age;
}
//复写equals以便HashSet集合和集合中一些比较方法调用
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new RuntimeException();
Student s = (Student)obj;
return this.name.equals(s.name)&&this.age==s.age;
}
//复写compareTo以便TreeSet集合调用
public int compareTo(Object obj)
{
Student s=(Student)obj;
if(this.age==s.age)
return this.name.compareTo(s.name);
return this.age-s.age;
//return new Integer(this.age).compareTo(new Integer(s.age)); 
}

}

class  TreeSetTest

{
public static void main(String[] args) 
{
TreeSet<Student> t=new TreeSet<Student>(new LenCompare());
t.add(new Student("wo1",12));
t.add(new Student("wosj",2));
t.add(new Student("wo1sdj",12));
t.add(new Student("wo6sd",12));
t.add(new Student("wo",22));

for (Iterator<Student> it=t.iterator(); it.hasNext(); )
{
Student s=it.next();
System.out.println(s.getName()+"....."+s.getAge());
}
}

}

//定义一个比较器,以姓名长度为主要比较

class LenCompare implements Comparator<Student>

{
public int compare(Student s1,Student s2)
{
int num=new Integer(s1.getName().length()).compareTo(new Integer(s2.getName().length()));
if (num==0)
{
return new Integer(s1.getAge()).compareTo(s2.getAge());
}
return num;
}

}

 

 

5:总结

如果你使用的集合要保证元素唯一:Set

  不需要排序:HashSet

    需要排序:TreeSet

如果你使用的集合不用保证元素唯一:List

  查询:ArrayList

  修改:LinkedList

  线程不安全:Vector

小技巧:

Array:说明底层数据结构是数组,查询快,增删慢

Link:说明底层数据结构是链表,查询慢,增删快

Hash:说明底层数据结构是哈希表,保证元素唯一,要依赖hashCode和equals。

Tree:说明底层数据结构是二叉树,有两种方案保证唯一和排序:

  A:Comparable -- compareTo

  B:Comparator -- compare


Map  集合

一、概述

1、简述:

        Map<K,V>集合是一个接口,和List集合及Set集合不同的是,它是双列集合,并且可以给对象加上名字,即键(Key)

2、特点:

        1)该集合存储键值对,一对一对往里存

        2)要保证键的唯一性。

 

二、Map集合的子类

        Map

            |--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。JDK1.0,效率低。

            |--HashMap:底层是哈希表数据结构。允许使用null键null值,该集合是不同步的。JDK1.2,效率高。

            |--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。

        Map和Set很像。其实Set底层就是使用了Map集合。

 

 

三、Map集合的常用方法

  A:添加元素

   put(Object key,Object value):把键值对元素添加到Map集合中

  B:删除元素

   remove(Object key):删除键为key的元素

  C:判断功能

   containsKey(Object key):判断Map集合中是否有键为key的键值

   containsValue(Object value):判断Map集合中是否有值为value的值

  D:获取元素

   get(Object key):根据键获取值

   keySet():获取Map集合的键的Set集合

   values():获取Map集合的值的Collection集合

   entrySet():获取Map集合的键值对的集合

  E:长度

   size():Map集合中键值对元素的个数
  遍历的思路:

   思路1:

    获取键值对的集合 keySet()

    遍历键集合,获取到每个键 Iterator hasNext(),next()

    通过键去找自己的值 get()

   思路2:

    键值对的映射项Map.Entry是Map做好的:

     Map.Entry<Key,Value>

    键值对集合 entrySet()

    遍历键值对集合,获取到每个键值对的映射项Map.Entry对象 Iterator hasNext(),next()

    通过键值对的映射项Map.Entry对象获取键和值 getKey(),getValue()

  案例演示:

   键和值都是字符串:

  

   Map<String,String> map = new HashMap<String,String>();

   map.put("张三", "北京");

   map.put("李四", "上海");

   map.put("王五", "天津");

   map.put("赵六", "重庆");

   map.put("田七", "陕西");

   //方式1

   Set<String> keySet = map.keySet();

   Iterator<String> keyIt = keySet.iterator();

   while(keyIt.hasNext())

   {

    String key = keyIt.next();

    String value = map.get(key);

    System.out.println(key+"***"+value);

   }

   //方式2

   Set<Map.Entry<String,String>> meSet = map.entrySet();

   Iterator<Map.Entry<String,String>> meIt = meSet.iterator();

   while(meIt.hasNext())

   {

    Map.Entry<String,String> me = meIt.next();

    String key = me.getKey();

    String value = me.getValue();

    System.out.println(key+"***"+value);

   }

(3)HashMap

  是如何保证键的唯一性:

  通过自定义对象的hashCode方法和equals方法。

  代码体现:键是自定义对象,值是字符串

  前提:Student重写了hashCode方法和equals方法。

  HashMap<Student,String> hm = new HashMap<Student,String>();

  Student s1 = new Student("科比", 20);

  Student s2 = new Student("霍华德", 22);

  Student s3 = new Student("易建联", 25);

  Student s4 = new Student("乔丹", 24);

  Student s5 = new Student("林书豪", 23);

  Student s6 = new Student("易建联", 25);

  Student s7 = new Student("乔丹", 24);

  hm.put(s1,"北京");

  hm.put(s2,"上海");

  hm.put(s3,"重庆");

  hm.put(s4,"天津");

  hm.put(s5,"武汉");

  hm.put(s6,"深圳");

  hm.put(s7,"石家庄");

  //遍历

  Set<Student> set = hm.keySet();

  Iterator<Student> it = set.iterator();

  while(it.hasNext())

  {

   Student key = it.next();

   String value = hm.get(key);

   System.out.println(key.getName()+"***"+key.getAge()+"***"+value);

  }

  

(4)TreeMap

  是如何保证键的唯一性和排序的:

  集合具备比较性:Comparator -- compare

  元素具备比较性:Comparable -- compareTo

(5)LinkedHashSet和LinkedHashMap

  通过链表保证有序

  通过哈希保证唯一

  LinkedHashSet:保证元素有序,唯一

  LinkedHashMap:保证键有序,唯一

(6)HashMap和Hashtable的区别:

  A:Hashtable是线程安全的,效率低。HashMap是线程不安全的,效率高。

  B:Hashtable的键和值都不能为null。HashMap可以允许null键和null值。



7:工具类的使用

(1)对数组操作的Arrays

  A:static String toString(数组)

  B:static void sort(数组)

    可以对对象数组进行排序。

   两种方式:

    元素具备比较性

    Arrays的sort方法具备比较性

  C:static int binarySearch(数组,值)

   前提:数组有序

  D:static <T> List<T> asList(T... t)

(2)对集合操作的Collections

  A:static void sort()

  B:static void reverse()

  C:static int binarySearch(集合,值)

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: