容器

来源:互联网 发布:linux编程获取串口参数 编辑:程序博客网 时间:2024/05/20 16:37
本章内容 :(1136)
  1.容器概念。
  2.容器API。
  3.Collection接口。
  4.Iterator接口。
  5.增强的for循环。
  6.Set接口。
  7.List接口和Comparable接口。
  8.Collections类。
  9.Map接口。
  10.自动打包、解包。
  11.泛型。
  
 引入原理:用来放对象的集合,如果用数组装要预定大小,不方便。浪费空间。
 J2SDK所提供容器API位于java.util包内。
 组织结构图:
 <interface>Collection -----><interface>Set /<interface>List
 <interface>Set ---------->HashSet/TreeSet
 <interface>List --------->LinkedList/ArrayList
 <interface> Map --------->HashMap/TreeMap
 set:没有顺序,不可以重复。(两个对象互相的equals就相当于重复)
 list:有顺序,可以重复。
 Map:接口定义了存储"key"-"value"
 
 Collection接口中所定义的方法:在java.lang.util包中。
 int size()
 boolean isEmpty()
 void clear();
 boolean contains(Object element);(还是equals不是引用相等)
 boolean add(Object element);
 boolean remove(Object element);
 Iterator iterator();
 boolean containsAll(Collection c);
 boolean addAll(Collection c);
 boolean removeAll(Collection c);
 boolean retainAll(Collection c);//求两个集合的交集。
 Object[] toArray();//把当前集合全部转换为对象类型的数组。
 小示例程序:
 public class DomeCollection {
public static void main(String[] args) {
//这里这样的用法,这样方便以后子类实现时更换子类的实现更方便灵活。
    Collection c = new ArrayList();
    c.add("hello");
    c.add(new Integer(100));//这时装的必须都是object栈里的数据随时可能清空。
    System.out.println(c.size());
    System.out.println(c);//会遍历里面每个元素。然后再调用相应的toString方法。
}
}


注意点: 
 1.容器类对象在调用remove/contains等方法时需要比较对象是否相等,
  这会涉及到对象类型的equals方法和hashCode方法;对于自定义的类型 。
  需要重写equals方法和hasCode方法(hashCode常用来做键时调用效率更高,并且唯一)
  相等的对象应该具有相等的hash Codes.
示例小程序:
public class Domehashcode {
public static void main(String[] args) {
Collection c = new HashSet();
c.add("hello");
c.add(new Integer(100));
c.add(new Name("f1","f2"));
c.remove("hello");
c.remove(new Integer(100));
System.out.println(c.remove(new Name("f1","f2")));
System.out.println(c.size());
System.out.println(c);
}
}


class Name{
String firstName;
String lastName;
Name(String firstName,String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return  firstName + lastName;
}
@Override
public int hashCode() {
return firstName.hashCode();
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Name){
Name name = (Name)obj;
return firstName.equals(name.firstName) && lastName.equals(name.lastName);
}
return super.equals(obj);
}
}


Iterator 接口:(多态)
 出现原因:因为每个集合底层实现原理不一样。需要一个统一遍历的方法。所以每种容器都有不同的实现。
 1.所有实现了Collection接口的容器类都有一个iterator方法用以返回在一个Iterator接口的对象。
 2.Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作。
 3.Iterator接口定义了如下方法:
boolean hasNext();//是否还有下一个。
Object next(); //把刚跳过的对象返回。
void remove(); //Iterator对象的remove方法是在迭代过程中删除元素的唯一的方法
              原因:因为iterator在遍历时会锁定,这里不能用Collection的remove方法。
 示例1.:
 public class DomeIterator {


public static void main(String[] args) {
     Collection c = new HashSet();//没有顺序
     c.add("hello");
     c.add("ok");
     c.add("yes");
     Iterator i = c.iterator();
     while(i.hasNext()){
    String str = (String) i.next();
    System.out.print(str + " ");
     }
}
}
 示例2:移除方法:
  public class DomeIterator2 {


public static void main(String[] args) {
     Collection c = new HashSet();//没有顺序
     c.add("hello");
     c.add("ok");
     c.add("yes");
     for( Iterator i = c.iterator(); i.hasNext();){
    String str = (String) i.next();
    if(str.length()<3){
    i.remove();
    }
     }
     System.out.println(c.size());
}
}


增强的for循环:
  1.增强的for循环对于遍历array 或Collection 的时候想当简便。
  2.缺陷:1.数组:不能方便的访问下标值。
    2.集合 :与使用Iterator相比,不能方便的删除集合中的内容。在内部也是调用的Iterator.
  总结:除了简单的遍历读出其中的内容外,不建议使用。
 示例:
 public class DomeFOR {
public static void main(String[] args) {
     int [] a = {1,3,2,5,2,9};
     for(int i:a){ //int i 这里是定义的数组里的类型
    System.out.println(i);
     }
     Collection c = new ArrayList();
     c.add("hello");
     c.add("yes");
     c.add("ok");
     for(Object obj:c){
    System.out.println(obj);//这里的String重写了toString.
     }
}





 


Set接口:
  Set接口是Collection的子接口,Set接口没有提供额外的方法。
  Set容器可以与数学时的“集合”的概念对应。
  J2SDK API 中所提供的Set容器类有HashSet ,TreeSet等。
  示例: public static void main(String[] args) {
Set s = new HashSet();
s.add("hello");
s.add(new Integer(100));
s.add("hello");
System.out.println(s);//[hello, 100]
}
}

  示例2:
    public static void main(String[] args) {
Set s1 = new HashSet();
Set s2 = new HashSet();
s1.add("a");
s1.add("b");
s1.add("c");
s2.add("a");
s2.add("b");
s2.add("d");
Set sn = new HashSet(s1);
sn.retainAll(s2);
Set su = new HashSet(s2);
su.addAll(s1);
System.out.println(sn);
System.out.println(su);
}
}


List接口:
 1. List接口是Collection的接口,实现List接口的容器有序,而且可以重复。
 2. List容器中的元素都对应一个整数型的序号,记载它在容器中的位置。可以根据序号存取容器中的内容。
 3. ArrayList LinkedList.
 object get(int index);
 object set(int index,object element);
 void add(int index);
 object remove(int index);
 int indexOf(object o);//在容器出现的第一个位置
 int lastIndexOf(object o);
 示例小程序:
  public class Domelist {


public static void main(String[] args) {
   List l1 = new LinkedList();
   for(int i=0;i<6;i++){
    l1.add("a" + i);
   }
   System.out.println(l1);//[a0, a1, a2, a3, a4, a5]
   l1.add(3,"a100");
   System.out.println(l1);
   l1.set(5, "a200");
   System.out.println(l1);
   System.out.println(l1.get(2));
   System.out.println(l1.indexOf("a200"));
   l1.remove(1);
   System.out.println(l1);//[a0, a2, a100, a3, a200, a5]
}
}
 
 List常用算法:
 类:java.util.Collections提供了一系列静态的方法,实现了基于List容器的一些常用算法。
 void sort(List) //
 void shuffle(List)//进行随机排列
 void reverse(List)//逆序排列
 void fill(List,Object)//用一个特定的对象重写整个List容器。
 void copy(List dext ,List src)//拷贝容器。
 int binarySearch(List ,Object)//二分法查找。
 示例:
 public class Domelistsort {


public static void main(String[] args) {
   List l1 = new LinkedList();
   for(int i=0;i<6;i++){
    l1.add("a" + i);
   }
   Collections.shuffle(l1);
   System.out.println(l1);
   Collections.sort(l1);
   System.out.println(l1);
   Collections.reverse(l1);
   System.out.println(l1);
   System.out.println(Collections.binarySearch(l1, "a0"));//这个结果 有问题
}
}


Comparable 接口:
 问题:上面的算法根据什么确定容器中对象的“大小”顺序?
 所有可以“排序”的类都实现了java.lang.comparable接口,Comparable接口中只有一个方法。
  public int compareTo(Object obj);如果传的对象不一致,比较没有意义。
  返回0表示: this == obj
  返回正数表示: this> obj 
  返回负数表示:this < obj
 实现了Comparable接口的类通过实现 comparaTo方法从而确定该类对象的排序方式。
  练习:对于姓名排序:
  public class Domecomparator {


public static void main(String[] args) {
    List l1 = new ArrayList();
    PeopleName p1 = new PeopleName("a1","c3");
    PeopleName p2 = new PeopleName("c1","c3");
    PeopleName p3 = new PeopleName("b1","c3");
    PeopleName p4 = new PeopleName("d1","c3");
    PeopleName p5 = new PeopleName("a1","a3");
    l1.add(p1);
    l1.add(p2);
    l1.add(p3);
    l1.add(p4);
    l1.add(p5);
    System.out.println(l1);
    Collections.sort(l1);
    System.out.println(l1);
}
}


class PeopleName implements Comparable{
@Override
public String toString() {
return firstname + " " + lastname;
}
String firstname;
String lastname;
PeopleName(String firstname,String lastname){
this.firstname = firstname;
this.lastname = lastname;
}
@Override
public int compareTo(Object o) {
PeopleName p = (PeopleName)o;
int la = lastname.compareTo(p.lastname);
return (la!=0 ? la : firstname.compareTo(p.firstname));
}
}
  
如何先把数据结构:
  Array读快改慢。
  Linked改快读慢。
  Hash两者之间。


Map接口:
  实现Map接口类用来存储键-值对。
  Map接口的实现类有HashMap和TreeMap等。
  Map类中存储的键-值对通过键来标识,所以键值不能重复。
  object put(object key,object value);
  object get(object key);
  object remove(object key);
  boolean containsKey(object key);
  boolean containsValue(object value);
  int size();
  boolean isEmpty();
  void putAll(Map m);
  void clear();
 练习 :
 public class DomeMap {
  public static void main(String args[]){
 Map m1 = new HashMap();
 Map m2 = new TreeMap();
 m1.put("one", new Integer(1));
 m1.put("two", 2);
 m1.put("three",3);//自动打包机制
 m2.put("a",new Integer(1));
 m2.put("b", new Integer(2));
 System.out.println(m1.size());
 System.out.println(m1.containsKey("one"));//true
 System.out.println(m2.containsValue(new Integer(2)));//true
 if(m1.containsKey("two")){
 int i =(Integer) m1.get("two");
 System.out.println(i);
 }
 Map m3 = new HashMap(m1);
 m3.putAll(m2);
 System.out.println(m3);
  }
}
 
 
 
Auto-boxing/unboxing(jdk1.5以后)
 1.在合适的时机自动打包、解包。
   1.自动将基础类型转换为对象。
   2.自动将对象转换为基础类型。
   自动打包:m1.put("one",1);(扔进去的仍然是一个对象)
   int i =(Integer) m1.get("one");
   
起因: JDK1.4以前类型不明确:
    1.装入集合的类型都被当做Object对待,从而失去了自己的实际类型。
    2.从集合取出时,往往需要转型,效率低,容易产生错误。
解决办法:
  1.在定义集合的时候同时定义集合中对象的类型。
  2.示例:1.可以在定义Collection的时候指定。
   2.也可以在循环的时候用Iterator指定。
好处:增强程序的可读性和稳定性。
什么样的类才能跟泛型:API里的类的后面如果有就可以跟泛型。


示例:public static void main(String[] args) {
List<String> l1 = new ArrayList<String>();
l1.add("aaa");
l1.add("bbb");
l1.add("ccc");
for(int i=0;i<l1.size();i++){
String s = l1.get(i);
System.out.println(s);
}

Collection<String> c = new HashSet<String>();
c.add("111");
c.add("222");
for(Iterator<String> i = c.iterator(); i.hasNext();){
String str = i.next();
System.out.println(str);
}
}
}


class Names implements Comparable<Names>{
@Override
public int compareTo(Names o) {
// TODO Auto-generated method stub
return 0;
}
}  
 
0 0