首页 > 学院 > 开发设计 > 正文

黑马程序员_集合

2019-11-14 20:54:33
字体:
来源:转载
供稿:网友
黑马程序员_集合

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

                                  集合1、集合和对象数组的区别:  数组的长度不可变,集合的可变;  数组可以存储基本数据类型和对象,集合只能存储对象。            

                                集合的框架图

                              集合派系的顶层接口Collection1、Collection集合存储对象的方法:  add(E e)将元素存储到集合中  addAll(Collection c)将一个集合添加到另外的集合中2、Collection集合提取对象的方法:  通过迭代器iterator中的方法;hasNext()和next()来取出  

 Iterator it=new iterator();   while(it.hasNext()){    System.out.PRintln(it.next());   }

3、Collection集合移除对象的方法:  boolean remove (Object o)移除一个对象,移除成功返回true。  boolean removeAll(Collection c)移除两个集合中的共性内容,成功返回true。4、Collection集合中的其他方法:  void clear()移除集合中所以元素  int size()返回集合中元素的个数  boolean contains(Object o)判断是否包含该对象,包含返回true。  boolean contains(Collection c)判断一个集合是否包含另一个集合,包含就返回true。  boolean retainAll(Collection c)将这两个集合的交集赋值给调用者,没有交集就是[]。   再判断调用者的元素是否改变,改变了就是true。  Collection中不常用的方法:  static reverse(List)反转集合  static fill(List,Object)替换集合                                        

        

                                          迭代器1、概念:  是取出集合中存储对象的方式。

2、原理:  

  在接口Collection中,定义了一个方法 Iterator iterator(),是集合中所有子类都具备的。

  iterator()返回的是一个Iterator接口类型,由于接口本身不能创建对象,所以返回的是接口的实现类对象3、Iterator接口中的三个方法:  boolean hasNext()判断集合中还有没有元素,有返回true。  Object next() 获取集合中的元素,可以看成数组中的arr[i]。  void remove()移除遍历的集合中的元素4、实现迭代器的三个步骤:  //通过集合对象的iterator()方法,返回一个Iterator接口的实现类对象  

  Iterator it=集合.iterator();  //使用迭代器对象的hasNext()方法,判断集合中还有没有对象可以被取出  while(it.hasNext()){  //使用迭代器对象的next()方法直接获取存在集合中的元素    it.next();  }

注:迭代器是获取集合中对象的通用方式。5、注意事项:  a.如果迭代器已经获取玩了,再次获取,会出现没有元素被取出的异常。  b.在迭代的过程中不要使用集合的方法改变集合的长度。  并发修改异常ConcurrentMOdificationException:  原因:使用集合的方法修改了集合的长度,而迭代器不知道。  c:一次迭代中,不能多次出现next()方法,否则可能出现异常,出现数据错乱。  因为每用一次next(),指针就会往后移一次。  解决办法:Object o=迭代器.next();

                                            List接口1、特点:  有序:取出的顺序和存的时候一样  具有下标  允许存储重复元素2、List集合存对象的方法:  add(int index,Objext o)index不能超过List集合原有的大小3、List集合获取对象的方法  A、一般情况下也是通过iterator()来获取   但是List派系有特有的迭代器ListIterator,ListIterator接口是继承Iterator的。   ListIterator接口的特点:  在迭代的过程中可以对集合中的元素进行添加、修改和删除。   ListIterator接口的方法:  add(Object o)  set(Object o)  boolean hasprevious()功能和hasNext()相同  Object previous()==next()  B、Object get(int index)获取指定下标的元素4、List集合修改对象的方法:  Object remove(int index)  Object set(int index,Object Obj)5、List集合其他方法:  List subList(int start,int end)注:List集合由于继承关系的存在,也有Collection集合的添加、修改和删除等方法。后面学习 的子类也是这样。

                                      ArrayList类1、属于List派系下的子类,具备List派系的所有特点:  有序,下标,重复   ArrayList自己的特点:  底层数据结构是数组  底层是可变数组,导致了查询快,增删慢  数组的大小默认是10,每次增长50%  线程不同步,不安全,但执行效率高 注:是通过复制数组的形式实现数组的可变。2、关于ArrayList集合的面试题  A、用户通过键盘输入姓名和成绩,姓名和成绩封装成学生对象,存到ArrayList中。  如果用户输入了"over",结束键盘的输入,迭代集合,迭代出已经存储的学生对象。

 1 public class Person { 2   private String name; 3   private int age; 4  5   public void setName(String name){ 6      this.name=name; 7   } 8   public void setAge(int age){ 9     this.age=age;10   }11   public String getName(){12     return name;13   }14   public int getAge(){15     return age;16   }17 18 19   public Person(){20 21   }22   public Person(String name,int age){23     setName(name);24     setAge(age);25   }26 27   public String toString(){28     return "Person:"+name+"..."+age;29   }30 }31 import java.util.*;32 public class ArrayListTest {33 public static void main(String[] args) {34   //创建一个集合,创建一个键盘输入的Scanner35   ArrayList array = new ArrayList();36   Scanner sc = new Scanner(System.in);37   //接受键盘输入38   while(true){39     String str = sc.nextLine().trim();40     //判断输入的是不是over 41   if("over".equals(str))42     break;43   //进行字符串的切割操作,空格的形式44   String[] s = str.split(" +");45   //姓名和成绩存储到ArrayList集合,成绩转成int46   array.add(new Student(s[0],Integer.parseInt(s[1])));47   }48   //创建迭代器,获取集合中的元素49   Iterator it = array.iterator();50   while(it.hasNext()){51     System.out.println(it.next());52   }53  }54 }

B、制作一个6位的不同字符的验证码,输出到控制台,用户输入,判断是对还是错。要求:6位不同的数子,字母和汉字。

import java.util.*;public class GetCode{  public static void main(String[] args){    Scanner sc=new Scanner(System.in);    //定义数组,保存一些字符    char[] ch={'a','v','1','3','6','你','黑','我','为','的','啊'};    //创建一个字符串缓冲区    while(true){    StringBuilder sb=new StringBuilder();    //因为只需6个字符,所以sb的长度为6就停止添加字符    while(sb.length()<6){    int num=new    Random().nextInt(ch.length);    if(sb.toString().contains(ch[num]+""))      continue;      sb.append(ch[num]);    }    System.out.println(sb);    //再比较字符串与输入的是否相等。相等就跳出循环,不等就刷新验证码。    String code=sc.nextLine();    if(sb.toString().equals(code)){    System.out.println("验证码正确!");        break;    }else{      System.out.println("验证码错误!");    }  } }}

3、去掉ArrayList中的重复元素要求ArrayList集合中对象重写equals()方法。

/*方法中返回一个新集合替换老集合*/public static ArrayList method(ArrayList oldArray){//定义新集合,存储去掉重复元素后的集合  ArrayList newArray=new ArrayList();  Iterator it=oldArray.iterator();  while(it.hasNext()){  Object obj=it.next();  if(!newArray.contains(obj))    newArray.add(obj);  }  return newArray; }contains()会调用equals();对象中重写的equals():public boolean void equals(Object obj){  if(this==obj)    return true;  if(obj==null)    return false;  if(obj instanceof Person){    Person p=(Person)obj;    return this.name.equals(p.name)&&this.age==p.age;  }}

                                        Vector类没有集合框架以前,存储对象只能依赖Vector。Vector底层的数据结构也是可变数组,但是它线程安全,运行效率慢,而且每次数组扩容是100%。所以被ArrayList取代了。                                          LinkedList类1、特点:  底层数据结构是链表实现,以记录对象地址的方式存储  查询慢,增删快  线程不安全,执行效率高2、LinkedList类特有的方法  addFirst()将元素添加到链表的开头  addLast()将元素添加到链表的结尾  Object getFirst()获取链表的开头  Object getLast()获取链表的结尾  Object removeFirst()移除链表的开头,返回被移除前的对象  Object removeLast()移除链表的结尾, 返回被移除前的对象JDK1.6开始,有n个新的方法,把以前的方法取代,不做掌握  offerFirst()-->addFist() 返回值不同add开头的没有返回值,offer开头返回boolean  offerLast()-->addLast()  peekFirst()-->getFirst()get开头没有元素,出异常,peek开头没有元素返回null,没异常  peekLast()-->getLast()  pollFirst()-->removeFirst()  pollLast()-->removeLast()

3、LinkedList模拟堆栈和队列,体现的是思想的转换:将jdk中的方法封装起来,让用户调用我们自己的方法来执行程序,而不是 用jdk中的方法。

import java.util.*;class MyMethod{  private LinkedList link=null;  public MyMethod(){  link=new LinkedList();}  public void add(Object obj){    link.add(obj);  }  //先进先出  public Object get(){    return link.removeFirst();  }  //先进后出  public Object get(int x){    return link.removeLast();  }  public boolean isEmpty(){    return !link.isEmpty();  } }public class LinkedListOut{  public static void main(String[] args)   {    MyMethod my=new MyMethod();    my.add("2");    my.add("3");    my.add("4");    while(my.isEmpty()){      System.out.println(my.get(2));    }  }}

                                     Set 接口1、Set集合派系的特点:  不允许存储重复元素  没有下标  无序的集合,存储的和取出的顺序不一样2、Set接口中的方法和Collection接口中的一致

                                        HashSet类1、HashSet类除有和Set接口一样的特点外,自身的特点是:  底层数据结构:哈希表,存储的是对象的哈希值  HashSet本身没有功能,功能来自于HashMap。HashSet调用HashMap的功能。2、HashSet的存储原理:  存储对象时,先调用对象的hashcode(),获取该对象的哈希值(十进制数)。HashSet看  存储过这个哈希值没。如果没有就将这个哈希值存到自己的哈希表中;如果有,就再  调用对象的equals()。如果相等就不存到HashSet集合中,不等就挂载到HashSet中原  有的哈希值下面。3、HashSet集合取出重复的元素,保证对象的唯一性    需重写hashCode()和equals():  

    public int hashCode(){      //利用name变量 age变量      return    name.hashCode()+age*13;    }    //同名的,和同年龄的对象,返回真    public boolean equals(Object obj){      if( this == obj)        return true;      if(obj == null)        return false;      if(obj instanceof Person){        Person p = (Person)obj;        return this.name.equals(p.name) && this.age == p.age;      }       return false;    }

4、hashCode和equals的问题 如果两个对象具有相同的哈希值,两个对象进行equals比较,不一定返回真; 如果两个对象进行equals比较,返回真,两个对象具有相同的哈希值吗,必须相同。

                                LinkedHashSet类---HashSet的子类LinkedListSet独有的特点:  有序的,基于哈希表的链表,线程不安全,执行效率高

                                            TreeSet类1、TreeSet独有的特点:  底层结构是二叉树;  对存储的对象自然排序;  线程不安全,执行效率高。2、将自定义的对象Person存储到TreeSet集合,出现了类型转换异常  ClassCastException :原因,Person不能被转成java.lang.Comparable  TreeSet中,需要对Person进行排序,可是你的Person对象,不具备自然顺序。3、TreeSet集合中使对象具备自然顺序:  自定义的类需实现Comparable接口,重写compareTo()方法;  或者,自定义比较器类,实现接口Comparator,重写Compare(Object o1,Object o2)。

 1   方法一: 2   //主要比较姓名,如果姓名一样,比较年龄。也可以主要比较年龄 3   public int compareTo(Object obj){ 4     //this 后进来的, obj先进来的对象 5     Person p = (Person)obj; 6     int num = this.name.compareTo(p.name); 7     return num == 0 ? this.age - p.age : num; 8   } 9   方法二:10   /*11   * 自定义比较器,对于TreeSet集合中存储的Person对象进行排序12   */13   Set set=new TreeSet(new Comparator());14   public class MyComparator implements java.util.Comparator{15     //重写compare方法,做什么事情,比较Person对象的年龄和姓名16     //    ts.add(new Person("lisi",20));17     // ts.add(new Person("zisi",21));18     public int compare(Object o1, Object o2){19     //o1 和 o2 比较一下,年龄,主要条件,年龄不同,不需要比较姓名20       Person p1 = (Person)o1;21       Person p2 = (Person)o2;22       //Person的变量,只能用get方法获取23       int num = p1.getAge() - p2.getAge();24       return num == 0? p1.getName().compareTo(p2.getName()) : num;25     }26 27   }

注:两个方法都是大于0,就存后面;等于0,就不存;小于0,存前面。

                                        泛型1、格式:   集合类<数据类型> 变量 = new 集合类<数据类型>();   数据类型,指定了这个集合,只能存储这个类型的对象。   如: ArrayList<E> boolean add(E e) E:看成是一个变量   ArrayList<String> 所有的E都变成了String   注意:存储基本数据类型,泛型必须写对应的包装类2、泛型的好处:  泛型的出现,将安全问题,由运行时期,提前到了编译时期  减少了代码,使用泛型避免类型的强制转换3、自定义的泛型,保证数据安全   泛型类,声明类的时候,加上泛型   泛型方法, 在方法上定义泛型,和类无关,需声明;  public<T> void method(T t){}  public static<T> void method(){}注意: 静态的方法的泛型不要和类上的一样。因为    静态的成员是优先于对象存在,用类名调用时无法指定    泛型的类型。    方法中的泛型是局部的泛型,不影响类名的泛型。     泛型接口,在接口名后面加上    通常定义实现类,实现接口的时候,不指定泛型,等待new实现类对象    的时候指定。class MyComparator <T> implements Comparator<T>(){}4、泛型的通配符和限定  上限限定 ? extends E 传递E类型,E的任意子类类型  下限限定 ? super E 传递E类型,E的任意父类类型  弊端:使用通配符后,不能强转。

                                           Map接口1、Map接口的特点:  一个键最多只能映射一个值  不允许出现重复的键2、Map接口的方法:  V put(K,V) 将键值对存储到集合。返回值,存储了重复的键,返回被覆盖之前的值  V get(K) 根据键获取值,传递一个键,返回键映射的值,没有这个键,返回null  Set<K> keySet()键存储到Set集合  Set<Map.Entry<K,V>> entrySet()2014/8/15映射关系对象保存到Set集合  V remove(K)移除指定的键对应的值,返回被移除前的值,没有移除成功,返回null  boolean containsKey(K)判断集合中,有没有这个键,有返回true  boolean containsValue(V)判断集合中个,有没有这个值,有返回true  Collection values()将集合中的所有值,保存到Collection集合3、获取Map集合中键值对的方式?  第一种,利用Map中的一个方法keySet(),Map集合中的键,存储到Set集合  迭代Set集合,获取出来的是所有的键  通过键获取值,Map接口中的get方法 

1   Map<String,Integer> map=new HaspMap<String,Integer>();2   Set<String> set=map.keySet();3   Iterator<String> it=set.iterator();4   while(it.hasNext()){5     String key=it.next();6     Integer value=map.get(key);7     System.out.println(key+"..."+value);8   }

第二种利用Map集合中的键值对映射关系获取Map接口中有一个方法entrySet(),获取键值对的映射关系对象Entry,将这个对象Entry存储到了Set集合迭代Set集合,获取出来的Set集合中存储的是映射关系对象Entry通过映射关系对象中的方法 getKey getValue

1 Map<String,Integer> map=new HasMap<String,Integer>();2 Set<Map.Entry<String,Integer>> set=map.entrySet();3 Iterator <Map.Entry<String,Integer>> it=map.iterator();4 while(it.hasNext()){5   Map.Entry<String,Integer> me=it.next();6   String key=me.getKey();7   Integer value=me.getValue();8  System.out.println(key+"..."+value);9 }

                                        HashMap类1、HashMap独有的特点  底层结构是哈希表,允许存储null值,null键  不同步,线程不安全,执行效率高2、保证存储到的HashMap中的键唯一性。自定义对象保证唯一性,自定义对象需重写hoseCode()和equals()。

                                      LinkedHashMap类-------HashMap的子类

1、特点:   底层结构是基于哈希表的链表实现的   键怎么存,怎么取   不同步,线程不安全,执行效率高

                                            TreeMap类1、TreeMap的特点:    底层数据结构是红黑树,记自然平衡二叉树    对键进行自然的排序,要求作为键的对象,具备自然排序或者自定义比较器    不同步,线程不安全,执行效率高

2、TreeMap使用方式和TreeSet是一致的,保证对象的自然顺序,或者定义比较器就可以了。在存储的时候,Set使用add,Map使用put。

                                      HashTable类

1、HashTable的特点:  底层数据结构式哈希表  线程安全,不允许存null值,null键   因为HashTable出了线程和null的区别,其他的和HashMap的一致,所以被HashMap取代了。但是HashTable的一个子类Properties至今   很活跃。

                                    Properties类---HashTable的子类1、Properties的特点:  线程安全,与IO流配合使用。这个集合的泛型已经定好了,键值的泛型都是String。2、Properties的两个特有的方法:  setProperty(String key,String value)  getProperty(String key)3、计算一个字符串中每个字符出现的次数:

 1 import java.util.*; 2 public class TreeMapTest { 3 public static void main(String[] args) { 4 String s = "asrrfegrr4gw34g"; 5 //String s = "aa"; 6 //建立TreeMap集合,键就是单个字符,值出现次数 7 TreeMap<Character,Integer> tm = new TreeMap<Character, Integer>(); 8 //将字符串变成字符数组,操作单个字符 9 char[] ch = s.toCharArray();10 for(int x = 0 ; x < ch.length ; x++){11 //遍历到每一个字符,字符当作键,到集合中获取值12 Integer i = tm.get(ch[x]);13 if(i==null){14 //说明键,不存在的,字符没有出现过,把字符当作键,值为1存储到集合15 tm.put(ch[x], 1);16 }else{17 //说明键存在,将值++后存储会集合18 19 tm.put(ch[x], ++i);20 }21 }22 System.out.println(tm);23 }24 }

                                          JDK1.5后的新特性1、增强for循环:只适合遍历数组和集合  格式:  for(数据类型 变量:集合或者数组){    输出(变量);  }2、可变参数格式:  方法名(数据类型...变量名)   注意事项:    可变参数的数据类型唯一    多个参数,可变参数放最后    可变参数只能写一个

                                 Collections集合工具类<List专用>1、凡是工具类里面的成员都是静态的2、集合工具类的方法:  static sort(List list)可以排序List集合,升序  static sort(List list,Comparator com)传递List,比较器,按照比较器对集合升序排序  static Comparator reverSEOrder()返回一个比较器,逆转了对象的自然顺序(Comparable)  static Comparator reverseOrder(传递比较器)返回比较器,逆转了传递的比较器的顺序  static int binarySerach(List list,Object key)集合的折半查找,如果找不到该元素,返回-插入点-1。插入点,就是将查找的元素,放在集合中个,保证集合有序,下标插入点  static reverse(List list)反转集合  static fill(List list,Object o)替换集合中的所有对象  static shuffle(List list)随机排列集合中的对象,洗牌  Collections工具类中有一组方法 synchronized开头的,将线程不安全的集合,变成线程安全的集合

                                              Arrays数组工具类数组工具类中的方法:  static sort(数组) 数组进行升序排序,快排  static int binarySerach(数组,查找的元素)数组的折半查找  static String toString(数组)不是重写Object,将数组变成字符串  static List asList(数组)数组转集合,List集合,集合长度不可变  2Collection接口方法 T[] toArray(T[] a) 集合变数组


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表