黑马程序员_java基础笔记(06)...集合

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ---------------------- 

JavaApi(其实就是java给我们提供的已经定义好的对象。工具对象:集合框架)1:Collection  2:Map集合 
 3:System(java.lang)  4:Runtime(java.lang)  5:Date(java.util)  6:Calendar(java.util)  7:Math类 (java.lang包)
 黑马程序员_java基础笔记(06)...集合
 
Collection
  |--List:元素是有序的,元素可以重复。因为该集合体系有索引。
    |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。
    |--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
    |--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。
  |--Set:元素是无序,元素不可以重复。

1: Collection(在java.util中)定义了集合框架的共性功能。
  ①,添加
    add(e);确保此 collection 包含指定的元素(可选操作)。
    addAll(collection);
  ②,删除
    remove(e);从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
    removeAll(collection);
    clear();移除此 collection 中的所有元素(可选操作)。
  ③,判断。
    contains(e);如果此 collection 包含指定的元素,则返回 true
    isEmpty();如果此 collection 不包含元素,则返回 true
  ④,获取
    iterator();返回在此 collection 的元素上进行迭代的迭代器。
    size();返回此 collection 中的元素数。
  ⑤,获取交集。
    retainAll();仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
  ⑥,集合变数组。
    toArray();返回包含此 collection 中所有元素的数组。
Ⅰ,add方法的参数类型是Object。以便于接收任意类型对象。
Ⅱ,集合中存储的都是对象的引用(地址)
 
List:特有方法。凡是可以操作角标的方法都是该体系特有的方法。
  增
    add(index,element);向列表的尾部添加指定的元素(可选操作)。
    addAll(index,Collection);
  删
    remove(index);移除列表中指定位置的元素(可选操作)。
  改
    set(index,element);用指定元素替换列表中指定位置的元素(可选操作)。
  查
    get(index):返回列表中指定位置的元素。
    subList(from,to);返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
    listIterator();返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
    int indexOf(obj):返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
    ListIterator listIterator();返回此列表元素的列表迭代器(按适当顺序)。
 
LinkedList: 特有方法:
    addFirst();将指定元素插入此列表的开头
    addLast();
    getFirst();返回此列表的第一个元素。
    getLast();
  获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException
 
    removeFirst();移除并返回此列表的第一个元素。
    removeLast();
  获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException
 
在JDK1.6出现了替代方法。
  offerFirst();在此列表的开头插入指定的元素。
  offerLast();
  peekFirst();获取但不移除此列表的第一个元素;如果此列表为空,则返回 null
  peekLast();
 
  pollFirst();获取并移除此列表的第一个元素;如果此列表为空,则返回 null
  pollLast();
 
List集合特有的迭代器。ListIterator是Iterator的子接口。
  在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以,在迭代器时,只能用迭代器的放过操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。
public interface Iterator<E>
 
对 collection 进行迭代的迭代器。迭代器取代了 Java Collections Framework 中的 Enumeration。
 
迭代器与枚举有两点不同:
  • 迭代器允许调用者利用定义良好的语义在迭代期间从迭代器所指向的 collection 移除元素。
  • 方法名称得到了改进。 
什么是迭代器其实就是集合的取出元素的方式。迭代器是取出方式,会直接访问集合中的元素。所以将迭代器通过内部类的形式来进行描述。
通过容器的iterator()方法获取该内部类的对象。
 
例:
//创建一个集合容器。使用Collection接口的子类。ArrayList
ArrayList al = new ArrayList();
al.add("java01");//add(Object obj);
Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。
 
方法boolean hasNext()
如果仍有元素可以迭代,则返回 true。(换句话说,如果 next 返回了元素而不是抛出异常,则返回 true)。
 
枚举就是Vector特有的取出方式。
  发现枚举和迭代器很像。其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。
 
|--Set元素是无序(存入和取出的顺序不一定一致),元素不可以重复。、
  |--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
  |--TreeSet:可以对Set集合中的元素进行排序。
 
保证元素唯一性的原理
     是通过元素的两个方法,hashCodeequals来完成。
     如果元素的HashCode值相同,才会判断equals是否为true。
     如果元素的hashcode值不同,不会调用equals。
注意,对于判断元素是否存在,以及删除等操作,
依赖的方法是元素的hashcode和equals方法。保证元素唯一性的依据:compareTo方法return 0.
 
TreeSet排序的第一种方式:让元素自身具备比较性。
  元素需要实现Comparable接口,覆盖compareTo方法。也种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式。
  当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。
 
泛型:JDK1.5版本以后出现新特性。用于解决安全问题,是一个类型安全机制。
好处
  1.将运行时期出现问题ClassCastException,转移到了编译时期,方便于程序员解决问题。让运行时问题减少,安全。,
  2,避免了强制转换麻烦。
泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候写泛型呢?通常在集合框架中很常见,只要见到<>就要定义泛型。其实<> 就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
 
泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定。那么可以将泛型定义在方法上。
 
特殊之处:
  静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
 
什么时候定义泛型类?
  当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展。现在定义泛型来完成扩展。
 
? 通配符。也可以理解为占位符。 
泛型的限定: 
  ? extends E: 可以接收E类型或者E的子类型。上限。 
  ? super E: 可以接收E类型或者E的父类型。下限
 
 
2:Map集合
接口 Map<K,V>
K - 此映射所维护的键的类型
V - 映射值的类型
该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
和Set很像。其实,Set底层就是使用了Map集合。
Map
  |--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。
  |--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。
  |--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
 
  1,添加。
    put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。
    putAll(Map<? extends K,? extends V> m) 
  2,删除。
    clear() 从此映射中移除所有映射关系(可选操作)。
    remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
  3,判断。
    containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true
    containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true
    isEmpty() 如果此映射未包含键-值映射关系,则返回 true
  4,获取。
    get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null
    size() 返回此映射中的键-值映射关系数。
    values() 返回此映射中包含的值的 Collection 视图。
    entrySet() 返回此映射中包含的映射关系的 Set 视图。
    keySet() 返回此映射中包含的键的 Set 视图。
 
map集合的两种取出方式:
  1,Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。
  2,Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry。Entry其实就是Map中的一个static内部接口。
 
为什么要定义在内部呢?因为有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。而且该事物在直接访问Map集合中的元素。
 
注意,当发现有映射关系时,可以选择map集合。因为map集合中存放就是映射关系
使用map集合?当数据之间存在这映射关系时,就要先想map集合。
例:
获取该字符串中的字母出现的次数。
希望打印结果:a(1)c(2).....
  通过结果发现,每一个字母都有对应的次数。说明字母和次数之间都有映射关系。当发现有映射关系时,可以选择map集合。因为map集合中存放就是映射关系。
思路:
  1,将字符串转换成字符数组。因为要对每一个字母进行操作。
  2,定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。
  3,遍历字符数组。将每一个字母作为键去查map集合。如果返回null,将该字母和1存入到map集合中。如果返回不是null,说明该字母在map集合已经存在并有对应次数。那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中,覆盖调用原理键所对应的值。
  4,将map集合中的数据变成指定的字符串形式返回。
import java.util.*;
class  Map{
  public static void main(String[] args) {
    String s= charCount("ak+abAf1c,dCkaAbc-defa");
    System.out.println(s);
  }
  public static String charCount(String str){
    //字符串变成数组
    char[] chs = str.toCharArray();
    //定义集合
    TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
    int count = 0;
    //遍历字符串
    for int x = 0; x<chs.length;  x++){
      //判断是不是字母
      if  (  !(chs[x]>=‘a‘  &&  chs[x]<=‘z‘   ||  chs[x]>=‘A‘  &&  chs[x]<=‘Z‘))
      continue;
      //字母chs[x]作为键找集合返回Integer
      Integer value = tm.get(chs[x]);
      if ( value! = null )
      count = value;
      count++;
      tm.put(chs[x],count);//直接往集合中存储字符和数字,为什么可以,因为自动装箱
      count = 0;
      /*if(value==null){
        tm.put(chs[x],1);
      }
      else{
        value = value + 1;
        tm.put(chs[x],value);
      }*/
  }
  //System.out.println(tm);
 
  //打印对应关系
  StringBuilder sb = new StringBuilder();
  Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
  Iterator<Map.Entry<Character,Integer>>  it = entrySet.iterator();
  while ( it.hasNext() ){
    Map.Entry<Character,Integer> me = it.next();
    Character ch = me.getKey();
    Integer value = me.getValue();
    sb.append ( ch+ "(" + value + ")" );
  }
  return  sb.toString();
 }
}
 
 
集合框架的工具类。
Collections:集合框架的工具类。里面定义的都是静态方法。
Collections和Collection有什么区别?
  Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。它有两个常用的子接口,List:对元素都有定义索引。有序的。可以重复元素。Set:不可以重复元素。无序。
  Collections是集合框架中的一个工具类。该类中的方法都是静态的,提供的方法中有可以对list集合进行排序二分查找等方法。
通常常用的集合都是线程不安全的。因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法将线程不安全的集合,转换成安全的。
 
Arrays:用于操作数组的工具类。里面都是静态方法。asList(T... a)返回一个受指定数组支持的固定大小的列表。
  asList:将数组变成list集合好处?可以使用集合的思想和方法来操作数组中的元素。注意:将数组变成集合,不可以使用集合的增删方法。因为数组的长度是固定。如果你增删。那么会反生UnsupportedOperationException。如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
  contains如果此映射将一个或多个键映射到指定值,则返回 true
  get返回列表中指定位置的元素。
  indexOf()返回此列表中首次出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。
  subList();返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
 
  集合变数组。 Collection接口中的toArray方法。
   1,指定类型的数组到底要定义多长?当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。所以创建一个刚刚好的数组最优。
   2,为什么要将集合变数组?为了限定对元素的操作。不需要进行增删了。
 
高级for循环
格式:
for(数据类型 变量名 : 被遍历的集合(Collection)或者数组)
{
}
对集合进行遍历。只能获取集合元素。但是不能对集合进行操作。迭代器除了遍历,还可以进行remove集合中元素的动作。如果是用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
 
传统for和高级for区别高级for有一个局限性。必须有被遍历的目标。建议在遍历数组的时候,还是希望是用传统for。因为传统for可以定义脚标。
 
 
JDK1.5版本出现的新特性。方法的可变参数。
  在使用时注意:可变参数一定要定义在参数列表最后面。
  可变参数。其实就是一种数组参数的简写形式。不用每一次都手动的建立数组对象。只要将要操作的元素作为参数传递即可。隐式将这些参数封装成了数组。
 
StaticImport  静态导入当类名重名时,需要指定具体的包名。当方法重名是,指定具备所属的对象或者类。
 
其他常用的API:
3:System(java.lang)

  System 类包含一些有用的类字段和方法。它不能被实例化。在 System 类提供的设施中,有标准输入、标准输出和错误输出流;对外部定义的属性和环境变量的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法。 

System:类中的方法和属性都是静态的。
  out:标准输出,默认是控制台。
  in:标准输入,默认是键盘。
 
获取系统属性信息:Properties getProperties();
 
Properties prop = System.getProperties();
//因为Properties是Hashtable的子类,也就是Map集合的一个子类对象。
//那么可以通过map的方法取出该集合中的元素。
//该集合中存储都是字符串。没有泛型定义。
 
//如何在系统中自定义一些特有信息呢?
System.setProperty("mykey","myvalue");
 
//获取指定属性信息。
String value = System.getProperty("os.name");
System.out.println("value="+value);
 
//可不可以在jvm启动时,动态加载一些属性信息呢?
String v = System.getProperty("haha");
System.out.println("v="+v);
 
//获取所有属性信息。
for(Object obj : prop.keySet()){
  String value = (String)prop.get(obj);
  System.out.println(obj+"::"+value);
}
 
4:Runtime(java.lang)

  每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。 

Runtime对象:该类并没有提供构造函数。说明不可以new对象。那么会直接想到该类中的方法都是静态的。发现该类中还有非静态方法。说明该类肯定会提供了方法获取本类对象。而且该方法是静态的,并返回值类型是本类类型。由这个特点可以看出该类使用了单例设计模式完成。该方式是static Runtime getRuntime();
class  RuntimeDemo{
  public static void main(String[] args) throws Exception{
    Runtime r = Runtime.getRuntime();
    Process p = r.exec("notepad.exe  SystemDemo.java");
    Thread.sleep(4000);
    p.destroy();
  }
}
 
5:Date(java.util)类 Date 表示特定的瞬间,精确到毫秒。SimpleDateFormat
 
//将模式封装到SimpleDateformat对象中。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日E hh:mm:ss");
 
//调用format方法让模式格式化指定Date对象。
String time = sdf.format(d);
System.out.println("time="+time);
long l = System.currentTimeMillis();
Date d1 = new Date(l);
System.out.println("d1:"+d1);
 
6:Calendar(java.util)

  Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEARMONTHDAY_OF_MONTHHOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。 Calendar rightNow = Calendar.getInstance();

两个练习:
  1,获取任意年的二月有多少天。
    思路:根据指定年设置一个时间就是 
      c.set(year,2,1)//某一年的3月1日。
      c.add(Calenar.DAY_OF_MONTH,-1);//3月1日,往前推一天,就是2月最后一天。
  2,获取昨天的现在这个时刻。
    c.add(Calenar.DAY_OF_MONTH,-1);
import java.util.*;
class  Calendar{
  public static void main(String[] args) {
    Calendar c = Calendar.getInstance();
    c.set(1980,2,1);   // 1980年的3月1日
    c.add(Calendar.DAY_OF_MONTH,-1);//减一是1980年2月的最后一天
    printCalendar(c);
  }
  public static void printCalendar(Calendar c){
    //月份编码表
    String[] mons = {"一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"};
    //星期编码表
    String[] weeks = {"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
    int index = c.get(Calendar.MONTH);
    int index1 = c.get(Calendar.DAY_OF_WEEK);
    //获取年
    sop(c.get(Calendar.YEAR)+"年");
    //查表法获取月
    sop(mons[index]);
    //sop((c.get(Calendar.MONTH)+1)+"月");
    //获取日
    sop(c.get(Calendar.DAY_OF_MONTH)+"日");
    //查表法获取星期
    sop(weeks[index1]);
    //sop("星期"+c.get(Calendar.DAY_OF_WEEK));
  }
  public static void sop(Object obj){
    System.out.println(obj);
  }
}
 
 
7:Math类 (java.lang包)
Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
 
UnsupportedOperationException不支持的操作异常
ClassCastException类转换异常
ConcurrentModificationException并发修改异常
 

--------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ---------------------- 

  

黑马程序员_java基础笔记(06)...集合

上一篇:Triangular Sums


下一篇:一道常考fork题挖掘