黑马程序员--集合框架学习小练习
--------- android培训、java培训、期待与您交流! ----------
3 练习大集合
3.1 Collection
Collection定义了集合框架的共性功能。
1,添加
add(e);
addAll(collection);
2,删除
remove(e);
removeAll(collection);
clear();
3,判断。
contains(e);
isEmpty();
4,获取
iterator();
size();
5,获取交集。
retainAll();
6,集合变数组。
toArray();
1,add方法的参数类型是Object。以便于接收任意类型对象。
2,集合中存储的都是对象的引用(地址)
什么是迭代器呢?
其实就是集合的取出元素的方式。
如同抓娃娃游戏机中的夹子。
迭代器是取出方式,会直接访问集合中的元素。
所以将迭代器通过内部类的形式来进行描述。
通过容器的iterator()方法获取该内部类的对象。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class CollectionDemo { public static void main(String[] args) { method_get(); } public static void method_get() { ArrayList al = new ArrayList(); //1,添加元素。 al.add("java01");//add(Object obj); al.add("java02"); al.add("java03"); al.add("java04"); /* Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。 while(it.hasNext()) { sop(it.next()); } */ for(Iterator it = al.iterator(); it.hasNext() ; ) { sop(it.next()); } }
3.2 List
Collection
|--List:元素是有序的,元素可以重复。因为该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。
|--Set:元素是无序,元素不可以重复。、
List:
特有方法。凡是可以操作角标的方法都是该体系特有的方法。
增
add(index,element);
addAll(index,Collection);
删
remove(index);
改
set(index,element);
查
get(index):
subList(from,to);
listIterator();
int indexOf(obj):获取指定元素的位置。
ListIterator listIterator();
List集合特有的迭代器。ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。
因为会发生ConcurrentModificationException异常。
所以,在使用迭代器时,只能用迭代器的方法操作元素,可Iterator方法是有限的,
只能对元素进行判断,取出,删除的操作,
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。
该接口只能通过List集合的listIterator方法获取。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import java.util.*; class ListDemo { public static void sop(Object obj) { System.out.println(obj); } public static void method() { ArrayList al = new ArrayList(); //添加元素 al.add("java01"); al.add("java02"); al.add("java03"); sop("原集合是:"+al); //在指定位置添加元素。 al.add(1,"java09"); //删除指定位置的元素。 //al.remove(2); //修改元素。 //al.set(2,"java007"); //通过角标获取元素。 sop("get(1):"+al.get(1)); sop(al); //获取所有元素。 for(int x=0; x<al.size(); x++) { System.out.println("al("+x+")="+al.get(x)); } Iterator it = al.iterator(); while(it.hasNext()) { sop("next:"+it.next()); } //通过indexOf获取对象的位置。 sop("index="+al.indexOf("java02")); List sub = al.subList(1,3); sop("sub="+sub); } public static void main(String[] args) { //演示列表迭代器。 ArrayList al = new ArrayList(); //添加元素 al.add("java01"); al.add("java02"); al.add("java03"); sop(al); ListIterator li = al.listIterator(); //sop("hasPrevious():"+li.hasPrevious()); while(li.hasNext()) { Object obj = li.next(); if(obj.equals("java02")) //li.add("java009"); li.set("java006"); } while(li.hasPrevious()) { sop("pre::"+li.previous()); } //sop("hasNext():"+li.hasNext()); //sop("hasPrevious():"+li.hasPrevious()); sop(al); /* //在迭代过程中,准备添加或者删除元素。 Iterator it = al.iterator(); while(it.hasNext()) { Object obj = it.next(); if(obj.equals("java02")) //al.add("java008"); it.remove();//将java02的引用从集合中删除了。 sop("obj="+obj); } sop(al); */ } }
3.2.1 ArrayList练习
1.去除ArrayList集合中的重复元素。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class ArrayListTest { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { ArrayList al = new ArrayList(); al.add("java01"); al.add("java02"); al.add("java01"); al.add("java02"); al.add("java01"); // al.add("java03"); /* 在迭代时循环中next调用一次,就要hasNext判断一次。 Iterator it = al.iterator(); while(it.hasNext()) { sop(it.next()+"...."+it.next()); } */ /**/ sop(al); al = singleElement(al); sop(al); } public static ArrayList singleElement(ArrayList al) { //定义一个临时容器。 ArrayList newAl = new ArrayList(); Iterator it = al.iterator(); while(it.hasNext()) { Object obj = it.next(); if(!newAl.contains(obj)) newAl.add(obj); } return newAl; } }
2.将自定义对象作为元素存到ArrayList集合中,并去除重复元素。
比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。
思路:
1,对人描述,将数据封装进人对象。
2,定义容器,将人存入。
3,取出。
总结:
List集合判断元素是否相同,依据是元素的equals方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Person { private String name; private int age; Person(String name,int age) { this.name = name; this.age = age; } public boolean equals(Object obj) { if(!(obj instanceof Person)) return false; Person p = (Person)obj; //System.out.println(this.name+"....."+p.name); return this.name.equals(p.name) && this.age == p.age; } public String getName() { return name; } public int getAge() { return age; } } class ArrayListTest2 { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { ArrayList al = new ArrayList(); al.add(new Demo()); al.add(new Person("lisi01",30));//al.add(Object obj);//Object obj = new Person("lisi01",30); //al.add(new Person("lisi02",32)); al.add(new Person("lisi02",32)); al.add(new Person("lisi04",35)); al.add(new Person("lisi03",33)); //al.add(new Person("lisi04",35)); //al = singleElement(al); sop("remove 03 :"+al.remove(new Person("lisi03",33)));//remove方法底层也是依赖于元素的equals方法。 Iterator it = al.iterator(); while(it.hasNext()) { Person p = (Person)it.next(); sop(p.getName()+"::"+p.getAge()); } } public static ArrayList singleElement(ArrayList al) { //定义一个临时容器。 ArrayList newAl = new ArrayList(); Iterator it = al.iterator(); while(it.hasNext()) { Object obj = it.next(); if(!newAl.contains(obj)) newAl.add(obj); } return newAl; } }
3.2.2 LinkedList 总结与练习
1,LinkedList:特有方法:
addFirst();
addLast();
添加元素,头插和尾插。
getFirst();
getLast();
获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException
removeFirst();
removeLast();
获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException
在JDK1.6出现了替代方法。
offerFirst();在此列表的开头插入指定的元素。
offerLast();在此列表的结尾插入指定的元素。
peekFirst();
peekLast();
获取元素,但不删除元素。如果集合中没有元素,会返回null。
pollFirst();
pollLast();
获取元素,但是元素被删除。如果集合中没有元素,会返回null。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class LinkedListDemo { public static void main(String[] args) { LinkedList link = new LinkedList(); link.addLast("java01"); link.addLast("java02"); link.addLast("java03"); link.offerLast("java04"); //sop(link); // sop(link.getFirst()); // sop(link.peekFirst()); //sop(link.getLast()); //sop(link.removeFirst()); //sop(link.pollFirst()); //sop("size="+link.size()); while(!link.isEmpty()) { sop(link.removeLast()); //sop(link.pollLast()); } } public static void sop(Object obj) { System.out.println(obj); } }
2,使用LinkedList模拟一个堆栈或者队列数据结构。
堆栈:先进后出 如同一个杯子。
队列:先进先出 First in First out FIFO 如同一个水管。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import java.util.*; class DuiLie { private LinkedList link; DuiLie() { link = new LinkedList(); } public void myAdd(Object obj) { link.addFirst(obj); } public Object myGet() { return link.removeLast(); } public boolean isNull() { return link.isEmpty(); } } class LinkedListTest { public static void main(String[] args) { DuiLie dl = new DuiLie(); dl.myAdd("java01"); dl.myAdd("java02"); dl.myAdd("java03"); dl.myAdd("java04"); while(!dl.isNull()) { System.out.println(dl.myGet()); } } }
堆栈只需把上面的代码改一个地方:只需把取元素方法改成从列表头开始取。
public Object myGet()
{
return link.removeFirst();
}
3.3 Set总结与练习
3.3.1 小总结
|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
Set集合的功能和Collection是一致的。
|--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
|--TreeSet:可以对Set集合中的元素进行排序。
底层数据结构是二叉树。
保证元素唯一性的依据:
compareTo方法return 0.
TreeSet排序的第一种方式:让元素自身具备比较性。
元素需要实现Comparable接口,覆盖compareTo方法。
这种方式也称为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式。
当元素自身不具备比较性时,或者具备的比较性不是所需要的。
这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式
3.3.2 大练习
1,HashSet基本示例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class HashSetDemo { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { HashSet hs = new HashSet(); sop(hs.add("java01")); sop(hs.add("java01")); hs.add("java02"); hs.add("java03"); hs.add("java03"); hs.add("java04"); Iterator it = hs.iterator(); while(it.hasNext()) { sop(it.next()); } } }
2,往HashSet集合中存入自定对象
比如:姓名和年龄相同为同一个人,重复元素。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class HashSetTest { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { HashSet hs = new HashSet(); hs.add(new Person("a1",11)); hs.add(new Person("a2",12)); hs.add(new Person("a3",13)); // hs.add(new Person("a2",12)); // hs.add(new Person("a4",14)); //sop("a1:"+hs.contains(new Person("a2",12))); // hs.remove(new Person("a4",13)); Iterator it = hs.iterator(); while(it.hasNext()) { Person p = (Person)it.next(); sop(p.getName()+"::"+p.getAge()); } } } class Person { private String name; private int age; Person(String name,int age) { this.name = name; this.age = age; } public int hashCode() { System.out.println(this.name+"....hashCode"); return name.hashCode()+age*37; } public boolean equals(Object obj) { if(!(obj instanceof Person)) return false; Person p = (Person)obj; System.out.println(this.name+"...equals.."+p.name); return this.name.equals(p.name) && this.age == p.age; } public String getName() { return name; } public int getAge() { return age; } }
3,TreeSet基本示例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class TreeSetDemo 2 { 3 public static void main(String[] args) 4 { 5 TreeSet ts = new TreeSet(); 6 7 ts.add(new Student("lisi02",22)); 8 ts.add(new Student("lisi007",20)); 9 ts.add(new Student("lisi09",19)); 10 ts.add(new Student("lisi08",19)); 11 //ts.add(new Student("lisi007",20)); 12 //ts.add(new Student("lisi01",40)); 13 14 Iterator it = ts.iterator(); 15 while(it.hasNext()) 16 { 17 Student stu = (Student)it.next(); 18 System.out.println(stu.getName()+"..."+stu.getAge()); 19 } 20 } 21 } 22 23 24 class Student implements Comparable//该接口强制让学生具备比较性。 25 { 26 private String name; 27 private int age; 28 29 Student(String name,int age) 30 { 31 this.name = name; 32 this.age = age; 33 } 34 35 public int compareTo(Object obj) 36 { 37 38 //return 0; 39 40 if(!(obj instanceof Student)) 41 throw new RuntimeException("不是学生对象"); 42 Student s = (Student)obj; 43 44 System.out.println(this.name+"....compareto....."+s.name); 45 if(this.age>s.age) 46 return 1; 47 if(this.age==s.age) 48 { 49 return this.name.compareTo(s.name); 50 } 51 return -1; 52 /**/ 53 } 54 55 public String getName() 56 { 57 return name; 58 59 } 60 public int getAge() 61 { 62 return age; 63 } 64 }
4,TreeSet第二种排序方式应用
当元素自身不具备比较性,或者具备的比较性不是所需要的。
这时需要让容器自身具备比较性。
定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。
定义一个类,实现Comparator接口,覆盖compare方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Student implements Comparable//该接口强制让学生具备比较性。 2 { 3 private String name; 4 private int age; 5 6 Student(String name,int age) 7 { 8 this.name = name; 9 this.age = age; 10 } 11 12 public int compareTo(Object obj) 13 { 14 15 //return 0; 16 17 if(!(obj instanceof Student)) 18 throw new RuntimeException("不是学生对象"); 19 Student s = (Student)obj; 20 21 //System.out.println(this.name+"....compareto....."+s.name); 22 if(this.age>s.age) 23 return 1; 24 if(this.age==s.age) 25 { 26 return this.name.compareTo(s.name); 27 } 28 return -1; 29 /**/ 30 } 31 32 public String getName() 33 { 34 return name; 35 36 } 37 public int getAge() 38 { 39 return age; 40 } 41 } 42 class TreeSetDemo2 43 { 44 public static void main(String[] args) 45 { 46 TreeSet ts = new TreeSet(); 47 48 ts.add(new Student("lisi02",22)); 49 ts.add(new Student("lisi02",21)); 50 ts.add(new Student("lisi007",20)); 51 ts.add(new Student("lisi09",19)); 52 ts.add(new Student("lisi06",18)); 53 ts.add(new Student("lisi06",18)); 54 ts.add(new Student("lisi007",29)); 55 //ts.add(new Student("lisi007",20)); 56 //ts.add(new Student("lisi01",40)); 57 58 Iterator it = ts.iterator(); 59 while(it.hasNext()) 60 { 61 Student stu = (Student)it.next(); 62 System.out.println(stu.getName()+"..."+stu.getAge()); 63 } 64 } 65 } 66 67 class MyCompare implements Comparator 68 { 69 public int compare(Object o1,Object o2) 70 { 71 Student s1 = (Student)o1; 72 Student s2 = (Student)o2; 73 74 int num = s1.getName().compareTo(s2.getName()); 75 if(num==0) 76 { 77 78 return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())); 79 /* 80 if(s1.getAge()>s2.getAge()) 81 return 1; 82 if(s1.getAge()==s2.getAge()) 83 return 0; 84 return -1; 85 */ 86 } 87 88 89 return num; 90 91 } 92 }
5,练习:按照字符串长度排序。
字符串本身具备比较性。但是它的比较方式不是所需要的。
这时就只能使用比较器。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 class TreeSetTest 3 { 4 public static void main(String[] args) 5 { 6 TreeSet ts = new TreeSet(new StrLenComparator()); 7 8 ts.add("abcd"); 9 ts.add("cc"); 10 ts.add("cba"); 11 ts.add("aaa"); 12 ts.add("z"); 13 ts.add("hahaha"); 14 15 Iterator it = ts.iterator(); 16 17 while(it.hasNext()) 18 { 19 System.out.println(it.next()); 20 } 21 } 22 } 23 24 class StrLenComparator implements Comparator 25 { 26 public int compare(Object o1,Object o2) 27 { 28 String s1 = (String)o1; 29 String s2 = (String)o2; 30 31 /* 32 if(s1.length()>s2.length()) 33 return 1; 34 if(s1.length()==s2.length()) 35 return 0; 36 */ 37 38 39 40 int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); 41 if(num==0) 42 return s1.compareTo(s2); 43 44 return num; 45 } 46 }
6,练习,给出字符串"90 -7 0 18 2 45 4"
将字符串中的数值进行排序。使用TreeSet完成。
思路
1,将字符串切割。
2,可以将这些对象存入TreeSet集合。因为TreeSet自身具备排序功能。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 class TreeSetTest2 3 { 4 public static void main(String[] args) 5 { 6 7 ArrayList al = new ArrayList(); 8 9 String str = "90 -7 0 18 2 45 4"; 10 11 String[] arr = str.split(" ");//将字符串以空格切割 12 13 TreeSet ts = new TreeSet();//定义TreeSet集合对象ts 14 15 //将切割后对象存入ts中 16 for(int x=0; x<arr.length; x++) 17 { 18 //ts.add(new Integer(arr[x])); 19 ts.add(Integer.parseInt(arr[x]));// 20 } 21 22 System.out.println(ts); 23 } 24 }