Java集合详解一
在学习集合之前,我们需要思考的是为什么要有集合?集合有什么用?
我们知道,在java中有数组的概念,数组可以用来存放一组数据。但是,数组是固定长度的,这样在使用的时候就会有很多的不方便,比如说资源的浪费。这个时候,我们就希望有一种可以动态改变大小的数组,那就是集合的作用了。
首先我们来看看常用集合类和接口的组织图。
快速访问Collection List ArrayList LinkedList Set HashSet TreeSet 集合输出
我们可以知道,Collection<E>单值的最大父接口。
Collection<E>作为单值操作的最大父接口,提供了一些对集合中元素的基本操作,在实际的开发中,我们基本上不会直接去使用Collection<E>,而是使用其子接口List<E>,Set<E>。
提供的全部方法:
No. | 方法 | 类型 | 描述 |
1 | public boolean add(E e) | 普通 | 向集合中添加指定元素 |
2 | public boolean addAll(Collection<? extends E> c) | 普通 | 向集合中添加一组元素,泛型指定了操作元素的上限 |
3 | public void clear() | 普通 | 清空所有的内容 |
4 | pbulic bllean contains(Object o) | 普通 | 判断集合中是否有指定的内容 |
5 | public boolean containsAll(Collection<> c) | 普通 | 判断集合中是否有指定的一组内容 |
6 | public boolean equals(Object o) | 普通 | 判断是否和指定对象相等 |
7 | public int hashCode() | 普通 | 返回哈希码 |
8 | public boolean isEmpty() | 普通 | 判断集合是否为空 |
9 | public Iterator<E> iterator() | 普通 | 为输出接口实例化,进行集合的输出 |
10 | public boolean remove(Object o) | 普通 | 删除集合中的指定元素 |
11 | public boolean removeAll(Collection<?> c) | 普通 | 删除集合中的指定一组元素 |
12 | public boolean retainAll(Collection<?> c) | 普通 | 保留集合中的指定一组元素 |
13 | public int size() | 普通 | 取得集合的长度 |
14 | public Object[] toArray() | 普通 | 以数组的形式取得集合的全部内容 |
15 | public <T> T[] toArray(T() a) | 普通 | 取得全部内容 |
此接口的定义如下:
public interface List<E> extends Collection<E>
可以看出来,List<E>接口直接继承了Collection<E>接口,并且对其进行了一定的扩展功能。
List<E>接口的最大特点是有序(即加入顺序)的。用户可以对每个元素插入的位置进行准确的控制。可以根据整数索引访问集合中的元素。
跟Set<E>不同的是,集合中允许重复的元素
增加的方法:
No. | 方法 | 类型 | 描述 |
1 | public void add(int index,E e) | 普通 | 在指定的位置处加入元素 |
2 | public boolean addAll(int index,Collection<? extends E> c) | 普通 | 在指定位置添加一组数据 |
3 | public E get(int index) | 普通 | 通过索引位置取出指定的元素 |
4 | public ListInterator<E> listIterator() | 普通 | 为Listiterator接口实例化 |
5 | public E remove(int index) | 普通 | 删除指定位置的元素 |
6 | public E set<int index,E e> | 普通 | 修改指定位置的元素 |
7 | public List<E> subList(int fromIndex,int toIndex) | 普通 | 截取子集合 |
List<E>毕竟还是一个接口,如果要想使用List<E>,则还要使用其子类。常用子类有ArrayList,Vector,LinkedList,Stack
此类的定义如下:
public class ArrayList<E> extends AbstratList<E> implements List<E>,RandomAccess,Cloneable,Serializable
实例:
package com.collection.list; import java.util.List; import java.util.ArrayList; public class ArrayListTest { public static void main(String args[]){ List<String> stringList=new ArrayList<String>(); stringList.add("元素三"); stringList.add("元素一"); stringList.add("元素二"); stringList.add("元素五"); stringList.add(2, "元素六"); for(int i=0;i<stringList.size();i++){ System.out.println(stringList.get(i)); } } }
此类的定义如下:
public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>,Deque<E>,Cloneable,Serializable
这是List接口的一个链表实现。提供先进先出操作
package com.collection.list; import java.util.LinkedList; public class LinkedListTest { public static void main(String args[]){ LinkedList<String> strList=new LinkedList<String>(); strList.add("第一次添加的元素"); strList.add(0, "在指定位置0处添加的元素 "); strList.addFirst("这是添加的第一个元素"); strList.addLast("这是添加的最后一个元素"); for(int i=0;i<strList.size();i++){ System.out.println(strList.get(i)); } System.out.println("-------获取并移除第一个元素-----------"); System.out.println(strList.poll()); System.out.println("------------------------"); for(int i=0;i<strList.size();i++){ System.out.println(strList.get(i)); } System.out.println("--------获取但不移除第一个元素---------"); System.out.println(strList.peek()); System.out.println("------------------------"); for(int i=0;i<strList.size();i++){ System.out.println(strList.get(i)); } } }
此接口的定义:
public interface Set<E> implements Collection<E>
此接口最大的特点是元素不允许重复。
需要使用Set接口的话,需要借助于它的两个常用子类
HashSet<E>:散列存放
TreeSet<E>:有序存放
此类定义如下:
public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, Serializable
使用实例
package com.collection.set; import java.util.HashSet; import java.util.Set; public class HashSetTest { public static void main(String[] args) { Set<String> hashSet=new HashSet<String>(); hashSet.add("B"); hashSet.add("C"); hashSet.add("B"); hashSet.add("A"); hashSet.add("D"); System.out.println(hashSet); } }
关于重复元素的说明:
如果此时将 String换成一个自定义类:
package com.collection.set; 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; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
可以发现,已经出现了重复的元素。
实际上在对象中,是通过equal()方法和hashCode()方法来判断元素是否相等的。
package com.collection.set; 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; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } @Override public boolean equals(Object obj) { if(this==obj){ return true; } if(!(obj instanceof Person)){ return false; } Person p=(Person)obj; if(this.name.equals(p.name)&&this.age==p.age){ return true; }else{ return false; } } @Override public int hashCode() { return this.name.hashCode()*age; } }
此时已经没有重复元素了。
此类定义:
public class TreeSet<E>extends AbstractSet<E>implements NavigableSet<E>, Cloneable, Serializable
使用实例:
package com.collection.set; import java.util.Set; import java.util.TreeSet; public class TreeSetTest { public static void main(String[] args) { Set<String> treeSet=new TreeSet<String>(); treeSet.add("B"); treeSet.add("C"); treeSet.add("B"); treeSet.add("A"); treeSet.add("D"); System.out.println(treeSet); } }
关于排序的说明:
我们这个实例中是使用的是系统提供的类:String,如果使用的是一个以下的自定义类呢:
package com.collection.set; public class Student { private String name; private int age; public Student() { super(); } public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { // TODO Auto-generated method stub return super.toString(); } }
可以发现报错了,简单来说,就是Student类是不可以比较的。
要想让一个自定义类能够比较,就必须要实现Commparable接口,并且覆写compareTo方法。
package com.collection.set; public class Student implements Comparable<Student>{ private String name; private int age; public Student() { super(); } public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { // TODO Auto-generated method stub return super.toString(); } @Override public int compareTo(Student s) { // 自定义Student类的比较原则 if(this.age>s.age){ return 1; }else if(this.age<s.age){ return -1; }else{ return 0; } } }
再次执行,就发现执行成功。
在Java中输出集合有以下几种方式:
·Iterator
·ListIterator
·foreach
·Enumeration
其中,Iterator是最常用的集合输出方法,基本上可以输出所以的集合。因为在Collection接口中继承了Iterable<E>接口。
Iterator的简单实例:
package com.collection.list; import java.util.Iterator; import java.util.List; import java.util.ArrayList; public class ArrayListIterator { public static void main(String args[]){ List<String> stringList=new ArrayList<String>(); stringList.add("元素三"); stringList.add("元素一"); stringList.add("元素二"); stringList.add("元素五"); stringList.add(2, "元素六"); Iterator<String> it=stringList.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
ListIterator
ListIteraotr是Iterator的子接口,最大的特点是可以进行前后的双向输出。只能输出List接口内容。
package com.collection.list; import java.util.List; import java.util.ArrayList; import java.util.ListIterator; public class ArrayListListIterator { public static void main(String args[]){ List<String> stringList=new ArrayList<String>(); stringList.add("元素三"); stringList.add("元素一"); stringList.add("元素二"); stringList.add("元素五"); stringList.add(2, "元素六"); ListIterator<String> it=stringList.listIterator(); //从前向后输出 while(it.hasNext()){ System.out.println(it.next()); } System.out.println("--------------------"); //从后向前输出 while(it.hasPrevious()){ System.out.println(it.previous()); } } }
foreach
不仅仅是数组,集合也可以使用foreach来输出。
package com.collection.list; import java.util.List; import java.util.ArrayList; public class ArrayListForeach { public static void main(String args[]){ List<String> stringList=new ArrayList<String>(); stringList.add("元素三"); stringList.add("元素一"); stringList.add("元素二"); stringList.add("元素五"); stringList.add(2, "元素六"); for(String str:stringList){ System.out.println(str); } } }
Enumeration
这是一个古老的接口,只支持输出Vector的集合。
package com.collection.list; import java.util.Enumeration; import java.util.Vector; public class VectorEnumeration { public static void main(String[] args) { Vector<String> vector=new Vector<String>(); vector.add("A"); vector.add("C"); vector.add("B"); vector.add("G"); vector.add("D"); Enumeration<String> em=vector.elements(); while(em.hasMoreElements()){ System.out.println(em.nextElement()); } } }