黑马程序员—java基础之集合

时间:2022-03-05 11:36:22

黑马程序员—java基础之集合

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

 

感恩,感恩,感恩!懂得感恩的人,才会是有福报的人!感谢所有发生的一切!

 

什么是集合:集合是一个容器. 还记得数组也是一个容器,那么他们之间有什么不同呢.

集合与数组比较

数组有什么特点?

                                     1.有顺序

                                     2.定长

                                     3.类型单一

集合特点:

                                     1.有顺序也可以没顺序

                                     2.集合长度可以随着元素的增加而增加

                                     3.集合中可以装入任何Object

Java中的集合类都在java.util包下

         Java中的集合元素全是Object类型的。

 

Collection集合

Collection(特点:有顺序也无顺序,可重复也不可重复)

它是一个接口,下面是它的子接口.

                   |---List:有顺序的可重复

                            |----ArrayList

                             |----LinkedList

                             |----Vector

                   |---Set  :无顺序不可重复 

                            |-----HashSet

                            |-----TreeSet

         重复的概念是两个元素做equals相等

 

Collection接口中声明的方法

1.add 向集合中添加元素

                            声明:public boolean add(Object obj)

                            作用:向集合添加元素obj

                                     参数:要添加的元素

                                     返回值:代表是否添加成功.

                   2.clear清空集合中的元素

                            声明:public void clear();

                            作用:清空集合中所有元素

                   3.contains判断集合中是否包含指定元素

                            声明:public boolean contains(Object obj)

                            作用:判断集合中是否包含指定元素,如果包含返回true,不包含返回false;

                                     注意:所谓的包含是指obj与集合中的元素做equals返回true.

                   4.size

                            声明:public int size();

                            作用:返回集合中元素的个数                                   

                   5.isEmpty

                            声明:public boolean isEmpty();

                            作用:判断集合中是否包含元素,如果没有任何元素返回true,有元素返回false

                   6.remove

                            声明:public boolean remove(Object obj)

                            作用:删除集合中的指定元素obj,如果删除成功返回true,否则返回false

                            注意:一次只能删除一个.

      Collection中的所有带All方法

                   1.addAll

                            声明:public boolena addAll(Collection c);

                            作用:求两个集合的并集

                                  简单说就是将两个集合中内容合并

                   2.containsAll

                            声明:public boolean containsAll(Collection c)

                            作用:判断集合c是否是集合的子集

                   3.removeAll

                            声明:public boolean removeAll(Collection c);

                            作用:将集合中包含的c集合中的所有元素删除。如果一个都不包含,返回false;

                   4.retainAll

                            声明:public boolean retainAll(Collection c);

                            作用:得到两个集合的交集.

      Collection中的迭代器(****)

                   想要将集合中的所有元素取出来,需要使用迭代器.

                   声明:public Iterator iterator();

                   Iterator它是对Collection进行迭代的迭代器(简单说就是用来遍历 Collection集合的)

                   Iterator接口中的方法

                            1.hasNext

                                     声明:public boolean hasNext();

                                     作用:判断集合中是否有元素可以进行迭代

                            2.next

                                     声明:public Object next();

                                     作用:将下一个迭代出来。

                            3.remove

                                     声明

                                               publicvoid remvoe();

                                     作用: 删除元素

                   使用迭代器遍历集合元素步骤

                            1.创建迭代器

                                     Iteratorit=集合对象.iterator();

                            2.通过迭代器判断是否有元素可以进行迭代

                                     while(it.hasNext()){它返回的是boolean 值

                                     }

                            3.通过迭代器将元素迭代出来

                                     Objectobj=it.next();

                                     集合中的元素在迭代出来后,都是Obejct

         关于迭代器的问题

                   iterator这个方法是声明在Collection接口中.

                   Iteratorit=集合对象.iterator();

                   在迭代的过程中不能对集合中元素进行修改,如果修改产生java.util.ConcurrentModificationException

                   关于迭代器中的remove方法与Collection中的方法区别

                            在对集合使用迭代器操作的过程中,不允许使用集合提供的可以修改集合中元素的方法。

                            例如:将集合中的元素删除,如果想要删除,必须使用迭代器提供的行为.

                  

                   迭代器的实现伪代码

                            interfaceIterator{

                            }

                            interfaceCollection{

                                     Iteratoriterator();

                            }

                            classArrayList implements Collection{

                                     publicIterator iterator(){

                                               returnnew Iter();

                                     }

                                     class Iter implements Iterator{

                                     }

                            }

                            classLinkedList implements Collection{

                                     publicIterator iterator(){

                                               returnnew LinkedIter();

                                     }

                                     classLinkedIter implements Iterator

                                     {

                                     }

                            }

                            Collection c=new ArrayList();

                            Iteratorit=c.iterator();

List集合

List集合的特点:有顺序可重复

         List是继承自Collection,Collection中的方法在List中都是存在。

List集合是有索引的,我们可以通过索引对其元素进行精确控制.

         List集合中的特性方法:

                   1.add方法

                            声明:public void add(int index,Object obj);

                            作用:在指定index索引位置添加元素

                   2.get方法(***)

                            声明:public Object get(int index);

                            作用:根据索引index得到对应位置上的元素

                   3.remove方法

                            声明:public Object remove(int index);

                            作用:将指定index索引位置上的元素删除,返回值就是删除的元素.

                   4.set方法

                            声明:public Object set(int index,Object obj)

                            作用:使用obj将index位置上的元素替换,返回值是被替换的元素.

List集合的遍历方式

1.通用方式 Iterator(适用于所有的Collection集合)

                                     通过从Collection继承的iterator方法

2.使用get(只适用于List集合)

                                     因为List集合是有顺序的,我们可以通过索引对其位置上进行控制

         3.使用List集合的特有的迭代器械  ListIterator(只适用于List集合)

                                     ListIterator是继承自Iterator,也就是在Iterator中声明的hasNext,next,remove方法它也有。

                                     但是它还提供了特有的方法

                                               add

                                               set

                                               ListIterator比Iterator功能增强

                                                        1.Iterator只能从上到下遍历,而ListIterator可以双向遍历

                                                        2.Iterator在迭代过程中不能修改,而ListIterator可以add ,set

ArrayList

它实现了List集合,所以在List集合中的方法它都可以用

                   我们主要研究,ArrayList的实现方式

                   ArrayList它的实现是使用可变数组

                   ArrayList类的特点:

                            1.它的底层实现是使用数组实现。

                            2.每一次数组会扩充50%

                            3.它是线程不安全。在单线程中使用。

//扩充方式伪代码:

                   classMyList{

                            privateObject[] obj;

                            privateint size=0;

                            publicMyList(){

                                     this(10);

                            }

                            publicMyList(int len){

                                     obj=newObject[len];

                            }

                            publicvoid add(Object o){

                                     obj[size]=o;

                                     //为了实现可以一直向MyList中不断的添加元素.

                                     change();

                                     size++;

                            }

                            privatevoid change(){

                                     Object[]old=obj;

                                    

                                     obj=newObject[old.length*3/2]; //在原来数组基础上扩大50%

                                     /*

                                     for(inti=0;i<old.length;i++){

                                               obj[i]=old[i];

                                     }*/

                            }

                            publicString toString(){

                                    

                                     StringBuilderbuilder=new StringBuilder();

                                     builder.append("[");

                                     for(inti=0;i<size;i++){

                                               builder.append(obj[i]).append(",");

                                     }

                                     builder.deleteCharAt(builder.length()-1);

                                     builder.append("]");

                                     returnbuilder.toString();

                            }

                   }

LinkedList

                   LinkedList的底层实现:双向链表

                   LinkedList特殊的方法:它可以很方便的操作集合的头尾元素.

                                        它对外提供了 get/remove/add

                   关于ArrayList与LinkedList集合区别?

                            ArrayList底层是使用数组实现,在内存中是连续的空间,那么他在做查找时会方法,

                            但是在做删除/修改时效率比较低.

                            LinkedList它的底层实现是链表实现,它在做查找时效率比较低。转为每一个元素

                            头存储的是上一个元素的地址,尾存储的是下一个元素的地址。

                            但是,它在做删除与修改时效率高。

                   LinkedList集合的特性方法

                            1.addFirst/addLast

                                     声明:public void addFirst(Object obj);

                                     作用:将obj元素添加到集合的首位置

 

                                     声明:public void addLast(Object obj)

                                     作用:将obj元素添加到集合的尾位置

 

                                     //在jdk1.6后提供两个替代的方法

                                     offerFirst

                                     offerLast

                                     它与我们addFirst与addLast区别在于它有返回值.

                            2.getFirst/getLast

                                     声明:public Object getFirst();

                                     作用:得到集合中的首元素

                                     声明:public Object getLast();

                                     作用:得到集合的尾元素

                                     在jdk1.6后提供替代方法

                                     peekFirst

                                     peekLast

                                     它们与getFirst/getLast区别,它们在集合为空时,返回的是null,而不会产生异常.

                            3.removeFirst/removeLast

                                     声明:public Object removeFirst();

                                     作用:删除集合中的首元素,返回的就是删除的这个元素

                                      声明:public Object removeLast()

                                     作用:删除集合中的最后一个元素,返回的是删除的这个元素.

                                     jdk1.6后替换的方法

                                     pollFirst

                                     pollLast

                                     它们区别在于pllFirst/pollLast列表为空时不会产生异常,而是返回null;

                            注意:对于getFirst/getLastremoveFirst/removeLast时,如果集合为空

                                 会产生异常.

Vector

                   Vector是早期应用集合时所使用的一个类.

                   ArrayList是Vector的替代类.

                   ArrayList是数组实现,它是每次增加50%,线程不安全.

                   Vector是数组实现  它每次拉回100%,线程安全的。

                   关于使用Enumeration遍历Vector

                            //1.得到Enumeration对象

                            Enumeration enu=v.elements();

                            //2.判断是否有元素可以进行迭代

                            while(enu.hasMoreElements()){

                                     //3.得到元素

                                      Object obj=enu.nextElement();

                                     System.out.println(obj);

                            }

        

List集合的总结

                   List有顺序可重复.

                            |----ArrayList

                                       它的底层实现是使用数组,每次增长50%,在做查询操作时效率高。是线程不安全。   

                            |----LinkedList

                                       它的底层实现是使用链表,它在做修改与删除时效率高。线程不安全。

                                       Linkedlist对于首尾元素操作比较方便.

                            |----Vector

                                               它的底层实现是数组,每次增长100%,效率低下,线程安全。

                   对于List集合的遍历方式

                            1.Iterator

                            2.get+索引

                            3.listIterator

Set

Set集合:无顺序不可重复

                   |----HashSet

                             它是由hash表支持的。这使用hashCdoe与equals来维护元素的唯一

                   |----TreeSet

         对于Set集合,如果想要遍历出所有元素,只能使用迭代器.        

         元素不重复,是指元素做equals为true,代表重复.

         HashSet怎样保证元素唯一

                   1.两个元素的hashCode不一样,不会判断equals,直接就能装入.

                   2.两个元素的hashCode一样,equals为false,能装入

                   3.两个元素的hashCdoe一样,equals为true,不能装入.

         做equals相等的对象的hashCode值应该一样.

         我们重写hashCode方法时怎样重写

                   就是将所有的做equals比较进应用的属性的hashCode值进行相加就可以,

                   为了减少重复的概率,我们可以定义一个质数,用这个质数与

                   所有的属性相乘,这样使用的hashCode值重复概率减少.

 

TreeSet集合的特点:有顺序不可重复

                            TreeSet集合怎样保证集合中的的元素是有顺序的,怎样保证元素的唯一性

                                     TreeSet集合中的元素必须有自然顺序或给集合指定了比较器。

                                     1.使用自然顺序

                                               就是实现 Comparable接口,重写compareTo方法

                                                        怎样排序:根据compareTo方法的返回值是正数还是负数,知道大于还是小于.

                                                        怎样唯一:根据compareTo方法的返回值为0,知道重复.

                                     2.使用比较器

                                               就是实现 Comparator接口  重写compare方法。

                                                        怎样排序:根据compare方法的返回值是正数还是负数,知道大于还是小于.

                                                        怎样唯一:根据compare方法的返回值为0,知道重复.

                                     注意:使用比较器要在创建集合时,就将其做为参数传递给集合。

                   什么时候使用比较器?

                             我们在开发中,发现集合中的元素已经存在了自然顺序,但是我们

                             想要进行排序的条件不是按照元素的自然顺序排序。这时就可以

                             自己去做比较器。

                   Set

                    |----HashSet 底层使用的hash表无顺序不重复,线程不安全的。 这是使用hashCode和equals方法保证元素唯一

                            |------LinkedHashSet

                                      元素装入顺序与取出顺序一致.线程不安全

                    |----TreeSet

                            底层使用二叉树有顺序,不可重复 线程不安全的.TreeSet在使用时效率比较低。

                                     它保证元素唯一有两种方式

                                               1.自然顺序 Comparable----compareTo(Object obj)

                                               2.比较器  Comparator----compare(Object o1,Object o1)

 

                  

                   怎样选择List与Set集合

                           

                            通常使用List,首先ArrayList ,如果是操作头尾元素还有频繁进行删除修改操作这时选择LinkedList

                            如果要求元素是不重复的。

                                     这时就选择Set ,首先HashSet

                                     如果要求对元素进行排序  TreeSet.

         jdk1.5,jdk1.6中TreeSet集合在使用时,如果是装入的第一个元素,

         这个时候它不会进行比较。也就是compareTo方法不会被执行.

         jdk1.7后集合中元素必须有自然顺序,也就是说当装入元素时,

         无论是否是第一个都会执行compareTo方法。

泛型

         泛型:其实就是用来限定类型.

         泛型的优点:

                   1.提高了我们程序的使用性.不需要在自己去做强转.

                   2.将原来在运行阶段处理的问题,放到了编译阶段.

                   3.提高安全性.

         在我们学习过程中,使用泛型最多的就是在集合中。

         泛型可以声明在类上,可以声明在方法上,可以声明在接口上。

         声明在类上的泛型,在整个类的范围内都可以使用。

         声明在方法上的泛型,只能在方法上使用。什么时候在方法上声明泛型?

         类上已经声明了泛型,但是在方法上我们不使用类上的泛型,而是自定义的

         一个,那么就可以在方法上声明,注意:在方法上声明时,泛型要定义在方法的返回值前面。

 

         通配符: ? 泛型中使用通配符的限定

                   <?extends E> 它是用来限定是E类型或是E的子类型.

                   <?super E>  只能是E类型或E的父类型.

         1.关于迭代器中使用泛型

                            集合上定义了泛型,我们在使用迭代器进行迭代操作时,必须给迭代器

                            也指定泛型,这样,在迭代出来时就不需要进行强制转换。

         2.关于泛型的擦除.

                            泛型只对编译阶段有效,而在运行阶段就失效。

                   /*

                   //以下两种操作,不建议使用,什么情况下能使用,就是为了兼容以前定义的集合.

                   Listlist1=new ArrayList<String>();

                   list1.add("abc");

                   list1.add(123);

 

                   List<String>list2=new ArrayList();

                   list2.add("abc");

                   list2.add(123);

                   */

                   ArrayList<String>list=new ArrayList<>(); //在jdk1.7后可以,简化操作,<>代表<String>

 

Map集合

Map集合是一种双列集合,它是采用key-value映射方式存储的。

         它的key值不能重复。

         Map接口下提供方法

                   1.怎样将元素添加到Map集合中.(*****)

                            声明: public Object put(Object key,Object value)

                            作用:向Map集合中添加key与value,

                                  注意:如果key值重复,它会将原本的映射关系破坏,

                                       用新的元素将旧的元素替换,而返回值就是旧的元素.

                   2.clear

                            声明:public void clear();

                            作用:清空集合

                   3.size

                            声明:public int size();

                            作用:得到集合的长度()

                   4.containsKey   containsValue

                            声明: public boolean containsKey(Object key)

                                  public boolean containsValue(Objectvalue)

                            作用:判断Map集合中是否包含指定的key或value

                   5.根据key取得value   get

                            声明:public Object get(Object key)

                            作用:根据指定的key值,得到对应的value。

                                 注意:如果没有映射关系,返回的是null.

                   6.remove

                            声明 public Object remove(Object key)

                            作用:根据key删除映射关系.

                                 返回值返回的是这个key对应的value值

                   7.values

                             声明:publicCollection values();

                             作用:得到Map集合中的所有的value的值的一个Collection集合。

         Map集合的遍历操作

                   1.使用keySet

                            1.通过Map的keySet方法得到的是key的Set视图.

                            2.通过Iterator对Set集合进行迭代,将Map中的所有的key得到了

                            3.通过Map的get方法,根据key得到对应的value.

                   2.使用entrySet

                            1.通过Map的entrySet方法得到的是key-value(其实就是Entry类型)映射的Set视图

                            2.通过Iterator得到Set集合中的所有的Entry对象.

                            3.通过Entry对象的getKey  getValue方法得到Map集合中的所有的key与value.

         Map集合与Collection集合的区别

                   1.Map是双列集合    Collection是单列集合

                   2.Map集合存储是使用put方法

                     Collection存储使用的是add方法.           

                   3.Map集合不能直接使用迭代器遍历.

                     使用keySet或entrySet方法,得到一个Set集合,在使用迭代器将Map集合中的元素迭代出来。 Collection取值使用迭代器 Iterator

HashMap

         HashMap

                   HashMap允许null值与null键,线程不安全。

                   它的底层实现是基于hash表的。

                   HashMap怎样保证其key值不重复?

                            使用元素的hashCode方法与equals方法保证.

         Hashtable

                   Hashtable不允许null值null键,它是线程安全。

TreeMap

它的底层实现使用的二叉树。它也是线程不安全的。

                   它怎样保证key的唯一性?

                            1.自然顺序

                            2.比较器

                            与我们之前讲过的TreeSet一样的原理.

Map集合总结

Map  双列集合

          |-----HashMap 底层使用hash表实现,它允许null值,null键,线程不安全。

                            HashMap使用元素的hashCode与equals方法来保证key的唯一。

                   |------LinkedHashMap

                                     它保证了装入时的key的顺序与取出时key的顺序一样。

          |-----Hashtable  它与HashMap的区别,除了不能null值,null键,线程安全。其它一样。

                   |------Properties

                               它是对配置文件进行映射的。

                               在早期开发中,经常的使用这样原的文件进行配置。

          |-----TreeMap  底层实现二叉树,它线程不安全。

                          它使用 自然顺序与比较器保证 key的唯一.

怎样选择使用什么集合

                            1.判断是存储单列还是双列,这样就可以选择Collection还是Map

                            2.

                                     2.1Collection

                                               如果没有要求,先List,List下首选ArrayList

                                               如果要求不重复  Set,Set下首先HashSet.

                                               对于LinkedList,TreeSet,它们的使用要根据上体的特性。

                                     2.2Map

                                               首选HashMap,如果要求进行排序,TreeMap.  

今日小练习:

将前面日志中的扑克牌程序用集合重写,并提供洗牌的功能.

Package com.itheima.test

import java.util.*;

class Test2{

   public static void main(String[] args){

      List<Poker> ps=newArrayList<Poker>();

      PokerTools.createPoker(ps);

      PokerTools.shuffle(ps);

      PokerTools.show(ps);

   }

}

//关于扑克的一些操作

class PokerTools{

   //生成扑克方法

   public static void createPoker(List<Poker> ps){

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

        for(int j=0;j<GlobalPoker.ns.length;j++){

           ps.add(newPoker(GlobalPoker.cs[i],GlobalPoker.ns[j]));

        }

      }

   }

 

   //洗牌的方法

   public static void shuffle(List<Poker> ps){

      Random ran=newRandom();

      for(inti=0;i<ps.size();i++){

        intn=ran.nextInt(ps.size());

        Poker p1=ps.get(i);

        Poker p2=ps.get(n);

        ps.set(i,p2);

        ps.set(n,p1);

      }

   }

   //显示扑克牌的方法

   public static void show(List<Poker> ps){

      for(inti=0;i<ps.size();i++){

           if(i%GlobalPoker.ns.length==0){

              System.out.println();

           }

           System.out.print(ps.get(i)+"  ");

      }

   }

}

//这个类中定义的是一个常量

class GlobalPoker{

   public static final String[] cs={String.valueOf((char)3),String.valueOf((char)4),String.valueOf((char)5),String.valueOf((char)6)};

   public static final String[] ns={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};

}

class Poker{

   String color;

   String number;

   public Poker(){}

   public Poker(String color,String number){

      this.color=color;

      this.number=number;

   }

// 重写toString方法

   public String toString(){

      return color+number;

   }

}

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