集合框架:
因爲每一個容器 對數據的存儲方式是不一樣的
這個存儲方式稱之爲:數據結構。
數組和集合類有何不同?
數組雖然可以存儲對象,但長度是固定的;
集合長度是可變的,數組中可以存儲基本數據類型,集合只能存儲對象
集合只用於存儲對象,集合長度是可以改變的,集合可以存儲不同類型的對象
Conllection
|--List:元素是有序的,元素可以重複,因爲該集合體繫有索引
|--ArrayList:底層的數據結構使用的是數組結構。 特點:查詢速度很快,但是增刪稍慢,線程不同步。 1.2版本出現
|--LinkedList:底層使用的是鏈表結構, 特點:增刪速度很快,查詢速度稍慢。
|--Vector:底層使用的是數組數據結構。 線程同步。被ArrayList替代了。 1.0版本出現
|--Set:元素是無序的,元素不可以重複
例子1:
public class ConllectionDemo {
/**
* @param args
*/
public static void main(String[] args) {
// base_mentod();
metod02();
}
public static void metod02() {
ArrayList al = new ArrayList();
al.add("java01");
al.add("java02");
al.add("java03");
al.add("java04");
ArrayList al01 = new ArrayList();
al01.add("java03");
al01.add("java04");
al01.add("java05");
al01.add("java06");
///去交集,al01中只會保留和al02中相同的元素。
// al.retainAll(al01);
print(al);
//al去掉與al01中相同的元素,保留剩下的元素
al.removeAll(al01);
print(al);
}
public static void base_mentod() {
// 創意一個容器,使用Conllection接口的子類ArryList類進行創建
ArrayList al = new ArrayList();
// 1.添加元素
al.add("java01");
al.add("java02");
al.add("java03");
al.add("java04");
// 打印集合
print(al);
// 2.判斷元素是否存在
print("java02時候存在:" + al.contains("java02"));
print("集合是否爲空:" + al.isEmpty());
// 3.獲取元素個數,集合長度
print("size:" + al.size());
// 4.刪除元素
al.remove("java02");
// 5.清空集合
al.clear();
print(al);
}
// 打印
public static void print(Object obj) {
System.out.println(obj);
}
}
特有方法:方式可以操作的角標的方法都是該體系特有的方法
add(index,element); 添加一個元素
addAll(index,Conllection); 添加一個集合
removed(index);
set(index,element);
get(index);
subList(from, to);
listIterator();
List集合特有的迭代器。 ListIterator是Iterator的子接口。
在迭代時,不可以通過集合對象的方法操作集合中的元素。
因爲會發生ConcurrentModificationException異常
所以,在迭代器時,只能用迭代器的方法操作元素,可是Iterator方法是有限的
只能對元素進行判斷,取出,刪除的操作
如果想要其他的操作如添加、修改等,就需要使用其子接口,ListIterator
add(E e) 將指定的元素插入列表
set(E e) 用指定元素替換 next 或 previous 返回的最後一個元素
hasNext() 以正向遍歷列表時,如果列表迭代器有多個元素,則返回 true(換句話說,如果 next 返回一個元素而不是拋出異常,則返回 true)。
next() 返回列表中的下一個元素。
hasPrevious() 如果以逆向遍歷列表,列表迭代器有多個元素,則返回 true。
previous() 返回列表中的前一個元素。
例子2:
public class ListDemo {
public static void main(String[] args) {
// 創建一個容器
ArrayList list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
//使用ListIterator在迭代過程中,可以進行對元素集合的操作
ListIterator it = list.listIterator();
System.out.println(list);
//從頭部來時遍歷
while(it.hasNext()){
Object obj = it.next();
if(obj.equals("2")){
// it.add("5"); //可以在ListIterator迭代過程中對元素進行操作
// it.remove();
// it.set("5"); //替換
}
}
System.out.println(list);
System.out.println("List hasPrevicous"+it.hasPrevious());
//從尾部開始進行遍歷
while(it.hasPrevious()){
System.out.println(it.previous());
}
}
public static void method(){
// 創建一個容器
ArrayList list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
// 創建一個新的容器
ArrayList list_1 = new ArrayList();
list_1.add("5");
list_1.add("6");
// 將集合list_1添加到list中
list.add(4, list_1);
// 查
Iterator ite = list.iterator();
while (ite.hasNext()) {
System.out.println("list:" + ite.next());
}
//改
list.set(0, "***");
System.out.println("修改後:"+list);
//刪除
list.remove(0);
System.out.println("刪除第一個下標:"+list);
}
}
public class ArrayListTest {
/**
* @param args
*/
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("1");
list.add("2");
list.add("1");
list.add("3");
list.add("2");
list.add("4");
System.out.println(list);
//去除重複元素之後
list = singleElement(list);
System.out.println(list);
}
public static ArrayList singleElement(ArrayList list){
ArrayList temp = new ArrayList();
Iterator it = list.iterator();
while(it.hasNext()){
Object obj= it.next();
if(!temp.contains(obj))
temp.add(obj);
}
return temp;
}
}
將自定義對象作爲元素存放在ArrayList集合中, 並去除重複的元素
對人描述,將數據封裝到人對象中
定義容器,將人存入
取出
class Person {
private String name;
private int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Person))
return false;
Person person = (Person) obj;
return this.name.equals(person.name) && this.age == person.age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class ArrayListTest1 {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<Person>();
list.add(new Person("李四01", 20));
list.add(new Person("李四02", 22));
list.add(new Person("李四03", 23));
list.add(new Person("李四02", 22));
list.add(new Person("李四02", 22));
list.add(new Person("李四04", 24));
list = singleElement(list);
Iterator it = list.iterator();
while(it.hasNext()){
Person p = (Person) it.next();
print(p.getName()+"---"+p.getAge());
}
}
public static ArrayList singleElement(ArrayList list) {
ArrayList temp = new ArrayList();
Iterator it = list.iterator();
while (it.hasNext()) {
Object obj = it.next();
if (!temp.contains(obj)) //這裏的contains依賴Object中的equals方法
temp.add(obj);
}
return temp;
}
public static void print(Object obj){
System.out.println(obj);
}
}
迭代器: 就是集合的取出元素的方式
每一個容器的數據結構不同,取出的細節也是不一樣的,但都是有共性內容的
那麼這些內部類都符合一個規則,該規則就是Iterator
如何獲取集合的去除對象?
通過一個對外提供的方法
iterator();
public class IteratorDemo {
public static void main(String[] args) {
//創建一個容器
ArrayList list = new ArrayList();
list.add("java01");
list.add("java02");
list.add("java03");
list.add("java04");
// 第一中方式:
// Iterator ite = list.iterator(); //獲取迭代器
// while(ite.hasNext())
// System.out.println(ite.next());
// 第二種方式:國外流行是用,比較減少資源消耗
for(Iterator ite = list.iterator(); ite.hasNext();)
System.out.println(ite.next());
}
}
addLast();
getLast();
獲取元素,但不刪除元素。 如果集合中沒有元素,會穿線NoSuchElementException異常
removeLast();
獲取元素,但是元素被刪除。 如果集合中沒有元素,會穿線NoSuchElementException異常
JDK1.6出現了替代方法:
offerLast();
peekLast();
獲取元素,但不刪除元素。 如果集合中沒有元素,會返回nul
pollLast();
獲取元素,但是元素被刪除。 如果集合中沒有元素,會返回nul
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList link = new LinkedList();
//從第一位添加
// link.addFirst("1");
// link.addFirst("2");
// link.addFirst("3");
// link.addFirst("4");
print(link);
// print(link.getFirst()); //當集合沒有元素時,這個方法會拋出異常
print(link.pollFirst()); //刪除
// print(link.getLast());
print(link.pollLast());
// print(link.removeFirst()); //獲取並刪除元素 當集合沒有元素時,這個方法會拋出異常
print(link.peekFirst()); //獲取
print(link.peekLast());
LinkedList link1 = new LinkedList();
//從最後以爲添加
link1.addLast("5");
link1.addLast("6");
link1.addLast("7");
link1.addLast("8");
print(link1);
// print(link1.getFirst());
// print(link1.getLast());
//遍歷
while(!link1.isEmpty()){
print(link1.removeFirst());
}
}
public static void print(Object obj){
System.out.println(obj);
}
}
需求:使用LinkedList模擬一個堆棧或者隊列數據結構
隊列:先進先出 (FIFO)
//隊列類
class Queue{
private LinkedList link;
Queue(){
link = new LinkedList();
}
public void add(Object obj){
link.addFirst(obj);
}
public Object get(){
return link.removeLast();
}
public boolean isNull(){
return link.isEmpty();
}
}
public class LinkedListTest {
public static void main(String[] args) {
Queue que = new Queue();
que.add("1");
que.add("2");
que.add("3");
que.add("4");
while(!que.isNull()){
System.out.println(que.get());
}
}
}
枚舉就是Vector特有的取出方式(線程安全,但效率不高)
發現枚舉和迭代器很像
其實枚舉和迭代器是一樣的(可以查文檔看看)
所以被迭代器取代了
public class VectorDemo {
public static void main(String[] args) {
//使用Vector創建一個新的容器
Vector vec = new Vector();
vec.add("1");
vec.add("2");
vec.add("3");
vec.add("4");
Enumeration enu = vec.elements();
while(enu.hasMoreElements()){
System.out.println( enu.nextElement());
}
}
}
|--hashSet是如何保證元素唯一性的呢?
是通過元素的兩個方法,hashCode和equals來完成。
如果元素的HashConde值相同,纔會判斷equals是否爲true
如果元素的HashConde值不同,不會調 用equals.
注意:對於判斷元素是否存在,以及刪除等操作,(依賴的方法是元素的hashCode和equals方法)
|---TreeSet:
例子:
public class HashSetDemo {
public static void main(String[] args) {
HashSet hs = new HashSet();
// HashSet集合是沒有重複元素的
hs.add("1"); // 方法返回的是boolean true
hs.add("1"); // false 重複添加的元素都無false的
hs.add("2"); // true
hs.add("3");// true
hs.add("3");// false
hs.add("4");// true
Iterator it = hs.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
需求: 將自定義對象作爲元素存放在HashSet集合中, 並去除重複的元素
實現
public class HashSetTest {
public static void main(String[] args) {
HashSet hash = new HashSet();
hash.add(new Student("lisi01", 21));
hash.add(new Student("lisi01", 21));
hash.add(new Student("lisi02", 22));
hash.add(new Student("lisi03", 23));
hash.contains(new Student("lisi01", 21));//true 判斷集合中是否有這一元素,依賴該元素的hashCode和equals方法
hash.remove(new Student("lisi01", 21)); // 刪除也依賴該元素的hashCode和equals方法
Iterator it = hash.iterator();
while (it.hasNext()) {
Student p = (Student) it.next();
System.out.println(p.getName() + ":" + p.getAge());
}
}
}
class Student {
private String name;
private int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
public int hashCode() {
return name.hashCode() + age * 37; // 這是爲了讓哈希表唯一(必須的*重點)
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Student))
return false;
Student person = (Student) obj;
return this.name.equals(person.name) && this.age == person.age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
底層數據結構是二叉樹。
保證元素唯一性的依據:compareTo方法return 0.
TreeSet排序的第一種方式:讓元素自身具備比較性。
元素需要實現Comparable接口,覆蓋compareTo方法
這種方式也成爲元素的自然排序,或者叫做默認排序
TreeSet的第二種排序方式:
當元素自身不具備比較性是,或者具備比較性不是所需要的。
這是就需要讓集合自身具備比較性
在集合初始化時,就有了比較方式;(創建一個類,實現Comparator比較器,複寫compareTo方法,將該類放到TreeSet的構造函數中)
往TreeSet集合中存儲自定義對象人
想按照人的年齡進行排序
例子1:
public class TreeSetTest {
public static void main(String[] args) {
TreeSet tree = new TreeSet();
tree.add(new People("lisi001",21));
tree.add(new People("lisi001",21)); //去掉重複對象
tree.add(new People("lisi002",22));
tree.add(new People("lisi005",22)); //當年齡相同時,判斷姓名進行排序
tree.add(new People("lisi003",23));
tree.add(new People("lisi004",24));
Iterator it = tree.iterator();
while(it.hasNext()){
People p = (People) it.next();
System.out.println(p.getName()+"_____"+p.getAge());
}
}
}
class People implements Comparable{ //一定要實現Comparable接口,爲TreeSet排序時使用到 (重點)
private String name;
private int age;
People(String name ,int age){
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object obj) {
if(!(obj instanceof People))
throw new RuntimeException("不是People類對象");
People p = (People) obj;
if(this.age > p.age)
return 1;
if(this.age == p.age){
return this.name.compareTo(p.name); //當年齡相同時,還用對姓名進行排序,String類應實現了Comparable接口
}
return -1;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
定義了比較器,將比較器對象作爲參觀傳遞給TreeSet集合的構造函數
例子2:
public class TreeSetTest01 {
public static void main(String[] args) {
TreeSet tree = new TreeSet(new MyComparator()); //使用構造函數進行排序
tree.add(new People01("lisi001", 21));
tree.add(new People01("lisi001", 21)); // 去掉重複對象
tree.add(new People01("lisi002", 22));
tree.add(new People01("lisi005", 22)); // 當年齡相同時,判斷姓名進行排序
tree.add(new People01("lisi003", 23));
tree.add(new People01("lisi004", 24));
Iterator it = tree.iterator();
while (it.hasNext()) {
People01 p = (People01) it.next();
System.out.println(p.getName() + "_____" + p.getAge());
}
}
}
class MyComparator implements Comparator{
@Override
public int compare(Object o1, Object o2) {
People01 p1 = (People01) o1;
People01 p2 = (People01) o2;
int num = p1.getName().compareTo(p2.getName());
//姓名相同
if(num == 0){
//當姓名相同時,比較年齡
return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));
}
return num;
}
}
class People01 {//implements Comparable { // 一定要實現Comparable接口,爲TreeSet排序時使用到 (重點)
private String name;
private int age;
People01(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
例子3:
public class TreeSetTest02 {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new Comparator(){
@Override
public int compare(Object o1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
int num = new Integer(s1.length()).compareTo(s2.length());
if(num == 0){
return s1.compareTo(s2);
}
return num;
}
});
ts.add("t");
ts.add("ac");
ts.add("zcf");
ts.add("acdr");
ts.add("acf");
ts.add("dddd");
Iterator it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}