黑马程序员 <java基础<集合知识点>>

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

collection集合中 子类List中的方法演示







class Demo{
public static void main(String[]args){


List list=new ArrayList();
getAllElements(list);


           }
//按原输入打印输出
public static void getAllElements(List list){  
list.add("Fuck");
                             list.add("Nick"); 
list.add("Fuck You"); 
    //使用迭代器 完成
Itreator it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
         
//遍历索引来完成
  for(int x=0;x<list.size();x++){
System.out.println("get:"+list.get(x));
}
              }   
}


集合框架 ListIterator的使用
  concurrentModificationException并发修改异常 
当对集合进行迭代时,在迭代的过程,如果用集合对象对元素进行了修改
迭代器是不知道的,所以在迭代的过程中就会发生不确定性.
为了避免这种情况的发生,在迭代时,不要使用集合对象对迭代中元素进行操作


但是我们还想在迭代的过程中对被迭代的元素进行更多的操作,该怎么办呢?
可以使用迭代器方法 但是Iterator的方法很郁闷 只有判断hasNext,获取next,删除remove三个方法


注意要解决这个问题,list接口中提供了一个特有的迭代器
这个迭代器就是ListIterator列表迭代器,就可以解决这个问题


介绍一下ListIterator
它的父接口是Iterator
一看其方法 , add remove set next 它就可以实现在迭代过程中进行元素增删改查的动作   它还支持逆向遍历. 


 注意:
使用ListIterator 只能对List集合使用
class Demo{
public static void main(String[]args){
         
                   List list=  new ArrayList();
                   ListIteratorDemo(list);
                }


public static void ListIteratorDemo(List list){
list.add("Fuck");
                              list.add("Nick"); 
list.add("Fuck You"); 
              System.out.println(list);
//获取列表迭代器
    ListIterator it=list.listIterator();    
                  
              while(it.hasNext){
Object obj=it.next();
  if(obj.equals("Fuck")){
it.add("For");
}
}
System.out.println(list); 
  }


collection
        ||---List 列表
               特点:
              1,有序(存储元素的顺序和取出元素的顺序一致)
              2,该集合中的元素都有索引,所以可以通过索引(角标) 来访问元素
              3,它可以存储重复元素
 常见子类对象:记住:具体的子类对象,我们要学习应该是该对象的特有的数据结                    构,以及相关的特点
               ||-----Vector:jdk1.0 就存在了 底层是数组结构. 可变长度数组
                            原理:一旦元数组长度不够,会创建新数组,将原数组的元素                          复制到新数组中,并将新元素添加到新数组中.
                         Vector 是同步的
              ||-----ArrayList:底层是数组结构,也是支持长度可变数组的.是不同步                    的.替代了Vector.因为效率高.查询效率很高.  但是增删效率慢
              ||-----LinkedList:底层是链接列表结构,简称链表结构. 是不同步的                       这个结构的好处:对元素的增删非常效率高,查询非常慢


    |---Set: 集: 中的方法和collection一致,只要重点主要它的子类对象即可
            特点:
            1,不包含重复元素. (这点是最大的特点)
            2,这个集合存入元素的顺序和取出元素的顺序不一定一致.(具体的容            器对象数据结构不同,顺序也有不同)
            ||---------HashSet:底层数据结构是哈希表,不保证顺序,是不同步的
   哈希表:提供数组的查询效率而出现的
   将要存储的元素先通过哈希算法算出一个哈希值来标识存储的位置,代   表着元素
   要找元素时,先将该元素通过哈希算法算出哈希值,在通过哈希值到    哈希表去查找
   特点:
   1,不关系元素的顺序
   2,提供了查询效率
   3,不可能出现重复元素,因为哈希值都不同.即使相同,会再次判断   两个元素的equals,内容是否相同,如果内容也相同,不存,如            果内容不同,存储.
   所以哈希表要保证元素的唯一性,必须要依赖于两个方法.
   1,hashCode                  
        2,equals
      
         ||--------TreeSet :可以给Set集合中的元素进行指定顺序的排序
                                  默认情况下,是通过元素的自然顺序排的序
                      它保证元素唯一性的依据是看比较方法的返回结果是0.是0.就                      视为元素相同.不存储
                    TreeSet排序的方式一:让元素自身具备比较性,需要实现                    Comparable接口,覆盖compareTo方法.这种比较方法成为自                   然顺序排序
                      
           如果元素自身不具备比较性或者具备的比较性(自然顺序)不是所需要的
           这是只能用第二种方式:
         TreeSet排序的方式二:让容器自身具备比较性.容器一初始化就具备了比      较功能.因为容器在对象构造时完成的 .通过查阅,有一个构造方法TreeSet(Comparator).在容器初始化时可以指定一个比较器.
需要实现Comparator接口,覆盖compare方法即可
所以这种方式成为比较器排序.


集合的技巧掌握:
明确具体集合对象名称的后缀:
如果后缀是List,都属于List体系,通常也是非同步的
如果后缀是Set,都属于Set体系,通常也是非同步的
这些体系中的其它子类对象,后缀不是所属接口名的,一般都是同步的 比如Vector
这在常用子类对象中通用


明确数据结构
对于jdk1.2版本的子类对象
后缀名是所属的体系
前缀名是技术数据结构的名称
比如:
ArrayList:看到Array,就要明确是数组结构.查询快
LinkedList:看到Link,就要明确链表结构,就要想到add get remove和first last
结合的方法,增删快.


HashSet:看到hash,就要明确是哈希表.查询快,而且唯一性
             就要想到元素必须覆盖hashCode方法和equals方法
TreeSet:看到Tree,就要明确是二叉树,可以对元素排序
   就要想到两种排序方式
 自然排序:Comparable接口.覆盖compareTo(一个参数)java.lang
 比较器:Comparator接口.覆盖compare(两个参数);java.util
判断元素唯一性的依据就是比较方法的返回结果return 0;




Vector中枚举接口演示
public static void main(String[]args){

Vector v=new Vector();
  list.add("Fuck");
                              list.add("Nick"); 
list.add("Fuck You"); 
               //枚举接口也是用来取出集合中的元素,但是枚举接口只能取出                 Vector集合中的元素
//枚举最后被迭代器取代
Enumeration en=v.elements();
      while(en.hasMoreElements()){
      System.out.prinltn(en.nextElement());


}


LinkedList演示


public static void main(String[]args){
 /*演示链表特有方法
   头尾操作方法
  addFirst();
 addLast();


getFirst();从头部获取元素,但不删除 如果没有元素会抛出
              异常NoSuchElementException
getLast();


 removeFirst();从头部获取元素,但删除  如果没有元素 会抛出                
                   异常NoSuchElementException
removeLast();
 LinkedList link=new LinkedList();
  link.addFirst("abc1");
  link.addFirst("abc2");
  link.addFirst("abc3");




//如果不为空
while(!link.isEmpty()){
System.out.println(link.removeLast());
                       }
//迭代器方法
/*Iterator it=link.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
*/
}


LinkedList模拟堆栈和队列
介绍两种常见的数据结构
1,队列:先进先出.
2,堆栈:后进先出


面试题: 请用LinkedList模拟一个堆栈或者队列数据结构


public class LinkedListTest{
pubic static void main(String[]args){


//创建我的队列对象
MyQueue myq=new MyQueue();
//给队列中添加元素
myq.myAdd("asd1");
myq.myAdd("asd2");
myq.myAdd("asd3");
myq.myAdd("asd4");


while(!myq.isNull()){
System.out.println(myq.myGet);
  }
              }
         }
//自定义一种队列数据结构的容器. 用LinkedList来完成
//就将链表封装到该结构中,最为最基础结构存在
public class MyQueue{


private LinkedList link=null;


 public MyQueue(){
 link=new LinkedList();
}
//往队列中添加元素


public void myAdd(Object obj){
//调用的是LinkedList的方法
 link.addLast(obj);
}
//获取队列中元素的方法
public Object myGet(){
return link.removeFirst();   //  改成return link.removeLast();就是堆栈:后进先出


}
//队列中是否为空
public boolean isNull(){
     return link.isEmpty();
                      }



ArrayList练习
定义一个功能,去除ArrayList中的重复元素
思路:
1,定义一个集合,用于存储唯一性的元素
2,迭代已有的集合,将每一个迭代到的元素都到新集合判断是否包含.
  如果包含就不存储,如果不包含就存储到新集合中
3,迭代结束,新集合中存储的都是不重复的元素


public static void main(String[]args){
ArrayList a1=new ArrayList();
a1.add("asd1");
a1.add("asd2");
a1.add("asd1");
a1.add("asd2");
System.out.println(a1);
a1=getSingleElmenetList(a1);
}
public static ArrayList getSingleElmenetList(ArrayList a1){
//1,创建一个新集合
ArrayList temp=new ArrayList();


//2,迭代原集合
Iterator it=a1.Iterator();
while(it.hasNext()){
Object obj=it.next();
if(!temp.contains(obj)){
temp.add(obj);
               }
         }
return temp;
   }
}


注意:ArrayList判断元素是否相同使用的equals方法
比如contains中就是依赖于equals方法
或者remove方法都是依赖于equals方法


尤其存储自定义对象时,该对象一定要覆盖equals方法,建立根据对象自身特点的判断相同的依据
  equals就是用于比较对象的内容的.


public class Person{


 private String name;
 private int age;
public person(){
super();
}
public Person(String name,int age){
super();
this.name=name;
this.age=age;
}
/*覆盖Object类中的equals方法,建立Person对象
 判断是否相同的依据.根据Person自身的特点来判断*/


//练习:存储一个自定义对象 并将其重复去除
public boolean equals(Object obj){

  if(!(obj instanceof Person))
               return false;
 
  Person p=(Person)obj; 
          /*
     if(this.name.equals(p.name)&&this.age==p.age)
               return true;
                return false;
         */
//注释中的代码优化  
return this.name.equals(p.name)&&this.age==p.age;


}


public String getName(){
return name;
                  }


public void setAge(String age){
this.name=name;
         }
public String getAge(){
return age;
                  }


public void setAge(String age){
this.age=age;
         }


//需导入
public static void main(String[]args){
ArrayList a1=new ArrayList();
a1.add(new Person("lisi1",21));
a1.add(new Person("lisi2",22));
a1.add(new Person("lisi2",22));
a1.add(new Person("lisi1",21));
System.out.println(a1);
a1=getSingleElmenetList(a1);
}
public static ArrayList getSingleElmenetList(ArrayList a1){
//1,创建一个新集合
ArrayList temp=new ArrayList();


//2,迭代原集合
Iterator it=a1.Iterator();
while(it.hasNext()){
Object obj=it.next();
if(!temp.contains(obj)){
temp.add(obj);
               }
         }
return temp;
   }
}




HashSet集合演示  顺序是无序  不同步
 
   import java.util.Iterator;
   
 public class HashSetDemo{
   
   public static void main(String[]args){
  
//创建容器
 HashSet hs=new HashSet();
    ha.add("NBA");
    ha.add("Fuck");
    ha.add("Nick");
    ha.add("PS");


Iterator it=hs.iterator();


while(it.hasNext()){


System.out.println(it.next());
               }
    }
  }


HashSet 练习- 存储自定义对象
往哈希表中存储自定义对象
往哈希表中的存储的自定义对象,必须覆盖hashCode方法,和equals方法


我也不知道这个对象到底存储到哪个容器中去
那就将hashCode,equals,toString全部覆盖
不覆盖也从Object类中继承了,那还不如覆盖,创建对象自身的判断相同的依据.
import java.util.HashSet;
import java.util.Iterator;
import cn.itcast.bean.Person;


public class HashSetTest{


public static void main(String[]args){


HashSet hs=new HashSet();


hs.add(new Person("lisi3",23));
hs.add(new Person("lisi4",24));
hs.add(new Person("lisi3",23));
hs.add(new Person("lisi2",22));
hs.add(new Person("lisi2",22));


Iterator it=hs.iterator();


while(it.hasNext()){
System.out.println(it.next());
                        }             
                 }
         }
public class Person{


 private String name;
 private int age;


public person(){
super();
}


public Person(String name,int age){
super();
this.name=name;
this.age=age;
}
//覆盖Object类中的hashCode方法,建立Person对象自己特定的哈希值算法
public int hashCode(){
final int NUMBER=27;


return name.hashCode()+age*NUMBER;//*27是为了尽量保证哈希值唯一
}




/*覆盖Object类中的equals方法,建立Person对象
 判断是否相同的依据.根据Person自身的特点来判断*/


//练习:存储一个自定义对象 并将其重复去除
public boolean equals(Object obj){

  if(!(obj instanceof Person))
               return false;
 
  Person p=(Person)obj; 
          /*
     if(this.name.equals(p.name)&&this.age==p.age)
               return true;
                return false;
         */
//注释中的代码优化  
return this.name.equals(p.name)&&this.age==p.age;
}


public String getName(){
return name;
                  }


public void setAge(String age){
this.name=name;
         }
public String getAge(){
return age;
                  }


public void setAge(String age){
this.age=age;
         }




TreeSet练习 存储自定义对象


public class TreeSetTest{


public static void main(String[]args){


TreeSet ts=new TreeSet();
ts.add(new Person("lisi2",20));
ts.add(new Person("lisi4",18));
ts.add(new Person("lisi1",19));
ts.add(new Person("lisi7",22));


Iterator it=ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
                        }
                    }
              }
/*要想让Person对象具备比较大小的功能
   就需要对Person对象进行功能的扩展
  让Person去实现Comparable接口,让Person具备自然顺序.覆盖compareTo方法
public class Person implements Comparable{


 private String name;
 private int age;


public person(){
super();
}


public Person(String name,int age){
super();
this.name=name;
this.age=age;
}
//覆盖Object类中的hashCode方法,建立Person对象自己特定的哈希值算法
public int hashCode(){
final int NUMBER=27;


return name.hashCode()+age*NUMBER;//*27是为了尽量保证哈希值唯一
}




/*覆盖Object类中的equals方法,建立Person对象
 判断是否相同的依据.根据Person自身的特点来判断*/


//练习:存储一个自定义对象 并将其重复去除
public boolean equals(Object obj){

  if(!(obj instanceof Person))
               return false;
 
  Person p=(Person)obj; 
          /*
     if(this.name.equals(p.name)&&this.age==p.age)
               return true;
                return false;
         */
//注释中的代码优化  
return this.name.equals(p.name)&&this.age==p.age;
}


public String getName(){
return name;
                  }


public void setAge(String age){
this.name=name;
         }
public String getAge(){
return age;
                  }


public void setAge(String age){
this.age=age;
         }
public String toString(){


 return name+":"+age;
}




public int compareTo(Object o){
/*进行对象比较的时候,通常,先比较主要条件,如果主要条件相同,在比较次要条件
如果想要按照人的年龄排序,如果年龄相同,在比较一次姓名.
麻烦写法
Person p=(Person)o;
if(this.age>p.age)
return this.name.compareTo(p.name);
return -1;


技巧性写法
Person p=(Person)o;
int temp=this.age-p.age;
return temp==0?this.name.compareTo(p.name):temp;


按照Person的姓名进行自然排序
Person p=(Person)o;
int temp=this.name.compareTo(p.name);
return temp==0?this.age-p.age:temp;


*/


/*这样判断 年龄重复的不输出不行 ,因为人相同是根据同姓名和同年龄完成的
  //按照Person对象的年龄进行排序,从小到大
Person p=(Person)o;
if(this.age>p.age)
return 1;
if(this.age<p.age)
return -1;
return 0;
*/
//return 1; 可以实现TreeSet,怎么存进去,怎么取出来
}


TreeSet:可以给其中的元素进行指定方式排序,使用的自然顺序
自然顺序:就是元素自身的具备的比较性实现了Comparable接口compareTO方法
TreeSet比较器排序
定义一个根据Person的Name进行比较的比较器
impor java.util.Comparator;


impor cn.itcast.bean.Person;


public class ComparatorByName implements Comparator{


public int compare(Object o1,Object o2){
Person p1=(Person)o1;
Person p2=(Person)o2;
int temp=p1.getName().compareTo(p2.getName());
return temp==0?p1.getAge()-p2.getAge():temp;
                 }
     }
TreeSet练习
要求是对字符串进行长度的排序
定义比较器
import java.util.Comparatior;
public class ComparatorByLength implements Comparator{


 pubic int compare(Object o1,Object o2){
 
                 String s1=(String)o1;
 String s2=(String)o2;
    int temp=s1.length()-s2.length();
 return temp==0?s1.compareTo(s2):temp;
                                    }
                         }
class TreeSetDemo{
            
public static void main(String[]args){


  TreeSet ts=new TreeSet(new ComparatorByLength());
ts.add("sda");
ts.add("fega");
ts.add("sdafewt");
ts.add("sdawqdqqw");


Iterator it=ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
             }
   }
  }


//泛型
接下来就有了新的思考方法,这其实源于jdk1.5的泛型技术
当一个类要操作的引用数据类型不确定的时候,可以将该类型定义一个形参
用到的这类时,有使用者来通过传递类型参数的形式,来确定要操作的具体的对象类型


意味着在定义这个类时,需要在类上定义形参.用于接收具体的类型实参
这就是将泛型定义在类上,这就是泛型类
什么时候使用泛型类呢?只要类中操作的引用数据类型不确定的时候,就可以定义泛型类


有了泛型类.,省去了曾经的强转和类型转换异常的麻烦


class Util{
private Object obj;
public void setObject(Object obj){
this.obj=obj;
}
public Object getObject(){
return obj;
   }   
}
//自定义泛型类
class Util<QQ>{
private QQ obj;
public void setObject(QQ obj){
this.obj=obj;
    }
public QQ getObject(){
return obj;
   }
}


//泛型定义方法
public static void main(String[]args){
Too12<String>t=new Too12<String>();


t.show("abc");        //t.show("abc");
t.myprint("SSMS");  //t.myprint(new Integer(4));运行异常
             //修改定义Too12<Integer> t1=new Too12<Integer>();
                           t1 .myprint(new Integer(4));
}
//在方法上定义泛型
class Too12<w>{
public void show(W w){
System.out.println("show:"+w.toString());
       }
public void myprint(W w){
System.out.println("myprint:"+w.toString());
        }


}
//在myprint方法上定义的泛型
public static void main(String[]args){
Too12<String>t=new Too12<String>();
t.show("abc");
t.myprint("hahah");
t.myprint(new Integer(4));


class Too12<w>{
//这个myprint方法,要操作的类型不确定的,但是不一定和调用该方法的对象指定的类型一致. 可以将泛型定义在方法上
public <A> void myprint(A a){
System.out.println("myprint:"+a.toString());
/*
//静态方法不能访问类上定义的泛型,如果需要泛型,该泛型只能定义在方法上
public static <Y> void myprint(Y a){
System.out.println("myprint:"+a.toString());
*/


public void show(W w){
System.out.println("show:"+w.toString());
       }


        }
}


//泛型---通配符
//简单的定义方式就是保证两边类型一致,但是也有其他情况
//泛型的通配符 ?
//当操作的不同容器中的类型都不确定的时候,而且使用的都是元素从Object类中继承的方法
这时泛型就用通配符 ? 来表示即可


创建一个用于迭代集合的功能


public static void printColl(ArrayList<?>a1){
Iterator<?>it=a1.iterator();
while(it.hasNext()){
System.out.println(it.next());
                     }
}
//泛型的限定
  明确具体类型代表一个类型
 明确?代表所有类型
能不能对操作的类型限定在一个范围之内呢?
比如:定义一个功能,只操作Person\类型或者Person的子类型
这时可以用 ? extends E :接收E类型或者E的子类型,这就是上限
下限: ? super E :接收E类型或者E的父类型











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值