黑马程序员_java基础6-集合框架Collection和泛型

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

@@(day14)Collection和泛型****************************************************************
数据多了用对象存,对象多了用集合存。
数组和集合类都是容器,有何不同?
--数组虽然也可以存储对象,但长度是固定的,集合长度是可变的。
--数组中可以存储基本数据类型,集合只能存储对象。
==集合只用于存储对象,集合长度可变,集合可以存储不同类型的对象。
  Collection     ||  Map(键值对)
 -List有序,可重复 -Set无序,不可重复||
--*ArrayList底层数组,不同步 --*HashSet哈希表  ||-*HashMap哈希表 -TreeMap二叉树
--*LinkedList底层链表  --TreeSet二叉树   ||
--Vector同步

Collection
|-List:元素是有序的,元素可以重复。因为该集合体系有索引。
 ||--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
 ||--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
 ||--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。
|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。、
 ||--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
  HashSet是如何保证元素唯一性的呢?
  是通过元素的两个方法,hashCode和equals来完成。
  如果元素的HashCode值相同,才会判断equals是否为true。
  如果元素的hashcode值不同,不会调用equals。
 ********复写public int hashCode()和public boolean equals(Object obj)
  注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
 ||--TreeSet:可以对Set集合中的元素进行排序。
  底层数据结构是二叉树。
  保证元素唯一性的依据:
  compareTo方法return 0.

 ********TreeSet排序的第一种方式:让元素自身具备比较性。
  implements Comparable接口,覆盖public int compareTo(Object obj)方法。
  也种方式也成为元素的自然顺序,或者叫做默认顺序。

 ********TreeSet的第二种排序方式。
  当元素自身不具备比较性时,或者具备的比较性不是所需要的。
  这时就需要让集合自身具备比较性。
  在集合初始化时,就有了比较方式。

注意:ArrayList构造一个初始容量为10的空列表,不够用的话,依次%50增加。节约空间。
      Vector构造一个初始容量为10的空列表,不够用的话,依次%100增加。

@@Collection定义了集合框架(List和Set)的共性功能。……%……%……%……%……%……%……%……%
1,添加
 add(Object e);//增加任意类型的元素,实际存放的是元素的地址。
 addAll(collection);//增加一个集合的元素。
2,删除
 remove(e);//移除元素
 removeAll(collection);//移除交集
 clear();//清空
3,判断。
 contains(e);//判断是否包含某元素
 isEmpty();//判断是否为空
4,获取
 for(Iterator it = al.iterator(); it.hasNext() ; )
  {sop(it.next());}
 size();//集合的大小,元素个数
5,获取交集。
 retainAll();//取出交集
6,集合变数组。
 toArray();//转成数组

1,add方法的参数类型是Object。以便于接收任意类型对象。
2,集合中存储的都是对象的引用(地址)。**********

@@接口Iterator<迭代器><迭代器><迭代器><迭代器>
/*
Itr是AbstractList的内部类并实现了Iterator接口。
public Iterator<E> iterator() {
 return new Itr();
    }
private class Itr implements Iterator<E>{...}
*/

======for(Iterator it = al.iterator(); it.hasNext() ; )//打印元素
  {sop(it.next());}
boolean hasNext()
          如果仍有元素可以迭代,则返回 true。
E next()
          返回迭代的下一个元素。
void remove()
          从迭代器指向的 collection 中移除迭代器返回的最后一个元素

什么是迭代器呢?
其实就是集合的取出元素的方式。
如同抓娃娃游戏机中的夹子。

迭代器是取出方式,会直接访问集合中的元素。
所以将迭代器通过内部类的形式来进行描述。
通过容器的iterator()方法获取该内部类的对象。

@@List特有的方法:带角标操作的函数。……%……%……%……%……%……%……%……%
@@List集合判断元素是否相同,只依赖元素的equals方法。自定义对象最好对其进行复写。
 @@其他的集合判断元素是否相同则不是只依据元素的equals方法。。
增-----------
void  list.add(int index,E element)在指定位置添加元素
boolean  list.addAll(index,Collection);index - 将指定 collection 的第一个元素所插入位置的索引(即在原集合中插入的位置)
删-----------
E  list.remove(int index)删除index角标上的元素
 remove(E  e);//移除元素(底层调用了元素的equals方法)###
改-----------
E  list.set(int index,E element) (特有)
查-----------
   contains(e);(底层调用了元素的equals方法)###
E   list.get(int index)返回指定位置的元素
List<E>   list.subList(int fromIndex,int toIndex)
ListIterator<E>  listIterator(int index)
int   list.indexOf(e):获取指定元素的位置。(底层调用了元素的equals方法)###

在迭代时,不可以通过集合对象list的方法来操作集合中的元素。
因为会发生ConcurrentModificationException异常。

所以,在迭代器时,只能用迭代器的方法来操作元素,可是Iterator接口中的方法是有限的,
只能对元素进行判断,取出,删除的操作,
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。
该接口只能通过List集合的listIterator方法获取。

@@ListIterator接口==List集合特有的迭代器<迭代器><迭代器><迭代器><迭代器><迭代器>
List集合特有的迭代器。ListIterator是Iterator的子接口。
======for(ListIterator it = al.listIterator(); it.hasNext() ; )//打印元素
  {sop(it.next());}
 void add(E e)
          将指定的元素插入列表(可选操作)。
 boolean hasNext()
          以正向遍历列表时,如果列表迭代器有多个元素,则返回 true(换句话说,如果 next 返回一个元素而不是抛出异常,则返回 true)。
 boolean hasPrevious()
          如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
 E next()
          返回列表中的下一个元素。
 int nextIndex()
          返回对 next 的后续调用所返回元素的索引。
 E previous()
          返回列表中的前一个元素。
 int previousIndex()
          返回对 previous 的后续调用所返回元素的索引。
 void remove()
          从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
 void set(E e)
          用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
总结下:
ListIterator中有:
hasNext,Next,nextIndex
hasPrevious,previous,previousIndex
增add(E e新元素)
删remove()
改set(E e新元素)

for(ListIterator li = al.Listiterator(); li.hasNext() ; )//取出元素
  {sop(li.next());}
@@Vector,JDK1.0的类,同步,容量10+%100... (JDK1.2开始Java Collections Framework,被ArrayList替代)
特有方法:(带element的都是,早期1.0的方法)
addElement(E obj)
...

@@枚举就是Vector特有的取出方式。
Enumeration<E> elements()
          返回此向量的组件的枚举。

 boolean hasMoreElements()
          测试此枚举是否包含更多的元素。
 E nextElement()
          如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。

发现枚举和迭代器很像。
其实枚举和迭代是一样的。

因为枚举的名称以及方法的名称都过长。
所以被迭代器取代了。
枚举郁郁而终了。

@@LinkedList 特有方法
addFirst()
addLast()

getFirst()
getFirst()
返回元素

removeFirst() ==》  JDK1.6后 pollFirst()
removeLast() ==》  JDK1.6后 pollLast()
//集合中无元素则抛出异常NoSuchElementEception ==>集合中无元素返回null
返回删除的元素

@@Set(具有Collection接口的方法)元素无序,元素不可重复!只用迭代器操作元素。
@@在添加元素,判断和删除时,先看hashCode值,再equals比较是否同一个对象
HashSet要重写hashCode方法和equals方法

public int hashCode()******************************
 {
  return this.name.hashCode()+this.age*33;
 }
public boolean equals(Object obj)******************
 {
  if(!(obj instanceof Person))
   return false;
  Person p = (Person)obj;//有泛型也得强转。
  return this.name==p.name && this.age==p.age;
 }
@@(day15TreeSet和泛型)**************************************************************************

|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。、
 |--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
  HashSet是如何保证元素唯一性的呢?
  是通过元素的两个方法,hashCode和equals来完成。
  如果元素的HashCode值相同,才会判断equals是否为true。
  如果元素的hashcode值不同,不会调用equals。
 ********复写public int hashCode()和public boolean equals(Object obj)
  注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
 |--TreeSet:可以对Set集合中的元素进行排序。
  底层数据结构是二叉树。
  保证元素唯一性的依据:
  compareTo方法return 0.

 ******* TreeSet排序的第一种方式:让元素自身具备比较性。
  元素implements Comparable接口,覆盖public int compareTo(Object obj)方法。
  也种方式也成为元素的自然顺序,或者叫做默认顺序。

 ******* TreeSet的第二种排序方式。(有比较器时,以比较器为主)
  当元素自身不具备比较性时,或者具备的比较性不是所需要的。
  这时就需要让集合自身具备比较性。
  在集合初始化时,就有了比较方式。
  class MyCompare implements Comparator定义的比较器
  public int compare(Object o1,Object o2)需要实现的方法
  初始化时TreeSet ts = new TreeSet(new MyCompare());
class Student implements Comparable//(第一种TreeSet)该接口强制让学生(集合中的元素)具备比较性。
{
private String name;
private int age;

Student(String name,int age)
{
 this.name = name;
 this.age = age;
}
public int compareTo(Object obj)//******必须做***************
{
 //return 0;表示两个元素相等 
 if(!(obj instanceof Student))
  throw new RuntimeException("不是学生对象");
 Student s = (Student)obj;

 int num = this.getAge()-s.getAge();
 if(num == 0)
  return this.getName().compareTo(s.getName());
 return num;
}
public String getName()
{
 return name;
}
public int getAge()
{
 return age;
}
}
class TreeSetDemo2
{
 public static void main(String[] args)
 {
 TreeSet ts = new TreeSet();//第一种实现元素比较性的方式!
 TreeSet ts = new TreeSet(new MyCompare());//第二种方式!用比较器的方法比较。
 ts.add(new Student("lisi02",22));
 ts.add(new Student("lisi02",21));
 ts.add(new Student("lisi007",20));
 ts.add(new Student("lisi09",19));
 ts.add(new Student("lisi06",18));
 ts.add(new Student("lisi06",18));
 ts.add(new Student("lisi007",29));
 //ts.add(new Student("lisi007",20));
 //ts.add(new Student("lisi01",40));

 Iterator it = ts.iterator();
 while(it.hasNext())
 {
 Student stu = (Student)it.next();//********没泛型时必做---------------
 System.out.println(stu.getName()+"..."+stu.getAge());
 }
}
}

class MyCompare implements Comparator<Student>//第二种实现元素比较性的方式=自定义的比较器。
{
public int compare(Object o1,Object o2)//********必须复写************
{
 Student s1 = (Student)o1;//将元素向下转型!没泛型时必做!----------
 Student s2 = (Student)o2;//

 int num = s1.name.compareTo(s2.name);
 if(num == 0)
  return (s1.age-s2.age);
 return num;
}
}
@@泛型Generic(JDK1.5后的)==》解决集合和迭代器的安全隐患。 是一个类型安全机制。
明确指定 集合      的元素类型为 <类型>
明确指定 迭代器      的元素类型为 <类型>
明确指定 Collection中一些接口的实现子类   的元素类型为 <类型>
明确指定 泛型类      的操作类型为 <类型>
明确指定 泛型方法     的操作类型为 <类型>

因为集合中的元素类型不同 可能会有安全隐患。
好处:
1,将运行时期出现问题ClassCastException(类型转换异常)转移到了编译时期。
2,避免了强制转换的麻烦。

class Student implements Comparable<Student>//(第一种TreeSet)该接口强制让学生(集合中的元素)具备比较性。
{
private String name;
private int age;

Student(String name,int age)
{
 this.name = name;
 this.age = age;
}
public int compareTo(Object obj)//******必须做***************
{
 if(!(obj instanceof Student))
  throw new RuntimeException("不是学生对象");
 //Student s = (Student)obj;//有泛型,不必强转!---------------

 int num = this.getAge()-s.getAge();
 if(num == 0)
  return this.getName().compareTo(s.getName());
 return num;
}
public String getName()
{
 return name;
}
public int getAge()
{
 return age;
}
}
class TreeSetDemo2
{
 public static void main(String[] args)
 {
 TreeSet<Student> ts = new TreeSet();//第一种实现元素比较性的方式!
 TreeSet<Student> ts = new TreeSet(new MyCompare());//第二种方式!用比较器的方法比较。
 ts.add(new Student("lisi02",22));
 ts.add(new Student("lisi02",21));
 ts.add(new Student("lisi007",20));
 ts.add(new Student("lisi09",19));
 ts.add(new Student("lisi06",18));
 ts.add(new Student("lisi06",18));
 ts.add(new Student("lisi007",29));
 //ts.add(new Student("lisi007",20));
 //ts.add(new Student("lisi01",40));

 Iterator it = ts.iterator();
 while(it.hasNext())
 {
 //Student stu = (Student)it.next();//********有泛型不用做了-----------
 System.out.println(stu.getName()+"..."+stu.getAge());
 }
}
}

class MyCompare implements Comparator<Student>//第二种实现元素比较性的方式=自定义的比较器。
{
public int compare(Object o1,Object o2)//********必须复写************
{
 //Student s1 = (Student)o1;//将元素向下转型!-----------------
 //Student s2 = (Student)o2;//

 int num = s1.name.compareTo(s2.name);
 if(num == 0)
  return (s1.age-s2.age);
 return num;
}
}
@@泛型类
/*
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,
早期定义Object来完成扩展。
现在定义泛型来完成扩展。
*/
class Utils<QQ>
{
 private QQ q;
 public void setObject(QQ q)
 {
  this.q = q;
 }
 public QQ getObject()
 {
  return q;
 }
}
@@泛型方法 泛型放返回类型的正前面
//泛型类上定义的泛型,在整个类中有效。如果该泛型被方法使用,-->
//那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。

//为了让类中的不同方法可以操作不同类型,而且类型还不确定。
//那么可以将泛型定义类中在方法上。

/*
特殊之处:
1,静态方法不可以访问类上定义的泛型。
2,如果静态方法操作的应用数据类型不确定,可以将泛型定义在静态方法上。
*/
class demo
{
 public <Q> void print(Q q)//泛型方法
 {
  System.out.println("print:"+q);
 }
 public  static <W> void method(W t)//静态泛型方法
 {
  System.out.println("method:"+t);
 }
}
class Demo<T>
{
 public  void show(T t)//和类上的泛型一致!
 {
  System.out.println("show:"+t);
 }
 public <Q> void print(Q q)//泛型方法
 {
  System.out.println("print:"+q);
 }
 public  static <W> void method(W t)//静态泛型方法,不能访问类上的泛型<T>
 {
  System.out.println("method:"+t);
 }
}
class GenericDemo4
{
 public static void main(String[] args)
 {
 Demo <String> d = new Demo<String>();
 d.show("haha");
 //d.show(4);
 d.print(5);
 d.print("hehe");

 Demo.method("hahahahha");
 }
}
@@泛型接口
interface Inter<T>
{
 void show(T t);
}
/*
class InterImpl implements Inter<String>
{
 public void show(String t)
 {
  System.out.println("show:"+t);
 }
}
*/
class InterImpl<T> implements Inter<T>
{
 public void show(T t)
 {
  System.out.println("show:"+t);
 }
}
class GenericDemo5
{
 public static void main(String[] args)
 {
  InterImpl<Integer> i=new InterImpl<Integer>();
  i.show(4);
  //InterImpl i=new InterImpl();
  //i.show("haha");
 }
}
/*
@@泛型限定 进行泛型扩张用的!
?  @@通配符。也可以理解为占位符。
? 任意类型:可以接受<?>任意类型
泛型的限定:一般在函数的形参上
? extends E: 可以接受E类型或E的子类型。 上限为E
? super E:  可以接受E类型或E的父类型。 下限为E
*/
public static void printColl(ArrayList<?> al)
{......}

public static void printColl(ArrayList<? extends Person> al)
{
 Iterator <? extends Person> it=al.iterator();
 ......
}

TreeSet<E> ts = new TreeSet<E>();
TreeSet<E> ts = new TreeSet<Collection<? extends E> c>();

TreeSet<E> ts = new TreeSet<Comparator<? super E> comparator>();
TreeSet中想要比较的元素是Student,但是可以传递进去一个Student或其父类Person的比较器。

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值