09 Collection,Iterator,List,listIterator,Vector,ArrayList,LinkedList,泛型,增强for,可变参数,HashSet,LinkedHashSet,TreeSet import com.fly.bean.Student; public class Demo1_Array { public static void main(String[] args) {
Student[] arr = new Student[5]; //创建引用类型数组
arr[0] = new Student("张三", 23);
arr[1] = new Student("李四", 24);
arr[2] = new Student("王五", 25); for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
/*Student [name=张三, age=23]
Student [name=李四, age=24]
Student [name=王五, age=25]
null
null*/
} } }
集合框架:
集合的由来
* 数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给
我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少
数组和集合的区别
* 区别1 :
* 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,
引用数据类型存储的是地址值
* 集合只能存储引用数据类型(对象),集合中也可以存储基本数据类型,但是在存储的
时候会自动装箱变成对象
* 区别2:
* 数组长度是固定的,不能自动增长
* 集合的长度的是可变的,可以根据元素的增加而增长
数组和集合什么时候用
* 1,如果元素个数是固定的推荐用数组
* 2,如果元素个数不是固定的推荐用集合
Collection(单列集合的根接口)->List有序,Set无序,不重复
List->ArrayList(数组实现),LinkedList(链表实现),Vector(数组实现)
Set->HashSet(哈希算法),TreeSet(二叉树算法)
Collection集合的基本功能:
import java.util.ArrayList;
import java.util.Collection; import com.fly.bean.Student; public class Demo2_Collection { @SuppressWarnings({ "rawtypes", "unchecked" }) //保持原始类型,不检查
public static void main(String[] args) {
Collection c = new ArrayList();
boolean b = c.add("abc");
boolean b1 = c.add(new Student("张三",12));
System.out.println(b);//true // List集合一直返回true,Set出现重复返回false
System.out.println(b1);//true System.out.println(c);//[abc, Student [name=张三, age=12]] System.out.println(c.contains("abc"));//true //是否包含
c.remove("abc");
System.out.println(c);//[Student [name=张三, age=12]]
System.out.println(c.size());//1
c.clear(); //清空
System.out.println(c);//[]
System.out.println(c.isEmpty());//true } }
集合的遍历:
import java.util.ArrayList;
import java.util.Collection; import com.fly.bean.Student; public class Demo3_Collection { public static void main(String[] args) {
// 集合的遍历
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d"); Object[] arr = c.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
} Collection arr1 = new ArrayList();
arr1.add(new Student("张三", 23));
arr1.add(new Student("李四", 24));
arr1.add(new Student("王五", 25)); Object[] arr2 = arr1.toArray();
for (int i = 0; i < arr2.length; i++) {
Student student = (Student)arr2[i]; // 下转型
System.out.println(student.getName()+" "+student.getAge());
}
} }
Collection集合的带All功能:
boolean addAll(Collection c)
boolean removeAll(Collection c) 删除的是交集,没有返回的是true
boolean containsAll(Collection c)
boolean retainAll(Collection c) 取交集,如果调用的集合不变就返回false
Iterator迭代器:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator; import com.fly.bean.Student; public class Demo4_Iterator { public static void main(String[] args) {
// 迭代
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
Iterator it = c.iterator(); //获取迭代器
while(it.hasNext()) {
System.out.println(it.next());
} Collection arr1 = new ArrayList();
arr1.add(new Student("张三", 23));
arr1.add(new Student("李四", 24));
arr1.add(new Student("王五", 25));
Iterator it1 = arr1.iterator();
while(it1.hasNext()) {
Student student = (Student)it1.next();
System.out.println(student.getName()+" "+student.getAge());
}
} }
迭代器原理:
迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取
都是不一样,那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,但是会让整个集合
体系过于臃肿,迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式,这样做
的好处有二,第一规定了整个集合体系的遍历方式都是hasNext()和next()方法,第二,代码有底层内部实
现,使用者不用管怎么实现的,会用即可
List:
import java.util.ArrayList;
import java.util.List; public class Demo1_List { public static void main(String[] args) {
// List
List list = new ArrayList();
list.add("a");
list.add(1,"b"); //index [0~size]
// list.add(5,"c");//IndexOutOfBoundsException System.out.println(list);//[a, b]
Object object = list.remove(1);//按照索引删除,返回的是被删除的元素
System.out.println(object);//b
System.out.println(list);//[a] Object object2 = list.get(0);
System.out.println(object2);//a
Object object3 = list.set(0, "A");
System.out.println(list);//[A]
} }
listIterator:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator; public class Demo2_List { public static void main(String[] args) {
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d"); /* Iterator iterator = list.iterator();
while(iterator.hasNext()) {
String string = (String)iterator.next();
if ("b".equals(string)) {
list.add("B"); //遍历的同时再增加元素,并发修改 ConcurrentModificationException
}
}*/
ListIterator listIterator = list.listIterator();////获取迭代器
while(listIterator.hasNext()) {
String string = (String)listIterator.next(); ////获取元素并将指针向 后移动
if ("b".equals(string)) {
listIterator.add("B");
}
}
System.out.println(list);//[a, b, B, c, d]
while(listIterator.hasPrevious()) {
System.out.print(listIterator.previous());//dcBba ////获取元素并将 指针向前移动
} } }
Vector:
import java.util.Enumeration;
import java.util.Vector; public class Demo3_Vector { public static void main(String[] args) {
Vector vector = new Vector();
vector.addElement("a");
vector.addElement("b");
vector.addElement("c");
vector.addElement("d"); Enumeration enumeration = vector.elements(); //获取枚举
while(enumeration.hasMoreElements()) { //判断集合中是否有元素
System.out.println(enumeration.nextElement());//获取集合中的元素
}
} }
数组和链表:
* A:数组
* 查询快修改也快 通过索引
* 增删慢 后面所有的元素都要移动
* B:链表
* 查询慢,修改也慢 从头找或从尾找
* 增删快
List的三个子类的特点:
*
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
Vector相对ArrayList查询慢(线程安全的)
Vector相对LinkedList增删慢(数组结构)
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
Vector和ArrayList的区别
Vector是线程安全的,效率低
ArrayList是线程不安全的,效率高
共同点:都是数组实现的
ArrayList和LinkedList的区别
ArrayList底层是数组结果,查询和修改快
LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
共同点:都是线程不安全的
List有三个子类,什么时候用?
查询多用ArrayList
增删多用LinkedList
如果都多ArrayList
ArrayList:
import java.util.ArrayList;
import java.util.Iterator; public class Demo1_ArrayList { public static void main(String[] args) {
// ArrayList去除集合中字符串的重复值(字符串的内容相同)
ArrayList list = new ArrayList();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c"); ArrayList newList = getSingle(list);
System.out.println(newList);//[a, b, c] }
public static ArrayList getSingle(ArrayList list) {
ArrayList newList = new ArrayList();
Iterator it = list.iterator();
while(it.hasNext()) {
Object object = it.next();
if (!newList.contains(object)) {//contains,remove的底层都依赖 equals方法
newList.add(object);
}
}
return newList;
} }
LinkedList:
import java.util.LinkedList; public class Demo2_LinkedList { public static void main(String[] args) {
LinkedList list = new LinkedList();
list.addFirst("a");
list.addFirst("b");
list.addFirst("c");
list.addFirst("d"); /*System.out.println(list); // [d, c, b, a]
System.out.println(list.getFirst()); //d
System.out.println(list.getLast()); //a
System.out.println(list.removeFirst());//d
System.out.println(list.removeLast());//a
System.out.println(list);//[c, b]
*/
System.out.println(list.get(0)); //d
} }
LinkedList模拟栈结构:
import java.util.LinkedList; public class Stack {
/*LinkedList模拟栈结构*/
private LinkedList list = new LinkedList(); // 进栈
public void push(Object object) {
list.addLast(object);
} // 出栈
public Object pop() {
return list.removeLast();
} // 判断是否为空
public boolean isEmpty() {
return list.isEmpty();
}
}
泛型:
import java.util.ArrayList;
import java.util.Iterator; import com.fly.bean.Person; public class Demo1_Generic { public static void main(String[] args) {
/* 泛型好处
* 提高安全性(将运行期的错误转换到编译期)
* 省去强转的麻烦
泛型基本使用
* <>中放的必须是引用数据类型
泛型使用注意事项
* 前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型 ) */
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("张三",19));
list.add(new Person("李四",18)); Iterator<Person> iterator = list.iterator();
while(iterator.hasNext()) {
Person person = iterator.next();
System.out.println(person); // Person [name=张三, age=19] Person [name=李四, age=18]
} } }
泛型的由来:
通过Object转型问题引入
/*把泛型定义在类上
定义格式
public class 类名<泛型类型1,…>*/
public class Tool<E> {
private E e; public E getObj() {
return e;
} public void setObj(E e) {
this.e = e;
} /*把泛型定义在方法上
定义格式
public <泛型类型> 返回类型 方法名(泛型类型 变量名)*/
public<T> void show(T t) {
System.out.println(t);
} }
增强for:
import java.util.ArrayList; public class Demo1_Foreach { public static void main(String[] args) {
/* 增强for概述
简化数组和Collection集合的遍历
格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}
底层依赖的是迭代器
*/
//遍历数组
int[] arr = {11,22,33,44,55};
for(int i:arr) {
System.out.println(i);
}
//遍历集合
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for(String string:list) {
System.out.println(string);
}
} }
迭代的删除:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator; public class Demo2_Del { public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("c");
list.add("d");
list.add("a");
list.add("a");
/* // 普通for循环,索引--
for (int i = 0; i < list.size(); i++) {
if ("a".equals(list.get(i))) {
list.remove(i--);
}
}*/ //迭代器while方式
/* Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
if ("a".equals(iterator.next())) {
// list.remove("a");//并发修改异常
iterator.remove();
} }*/ /* //迭代器for方式
for(Iterator<String> iterator=list.iterator();iterator.hasNext();) {
if ("a".equals(iterator.next())) {
iterator.remove();
}
}
System.out.println(list);//[c, d]
*/
//补充:
/* ListIterator<String> iterator = list.listIterator();
while (iterator.hasNext()) {
if ("a".equals(iterator.next())) {
iterator.remove();
iterator.add("A");//ListIterator有add,Iterator没有
} }
System.out.println(list);//[A, A, c, d, A, A]
*/
//增强for不能删除,只能遍历
} }
可变参数...
public class Demo3_ChangeableArgs {
/* 可变参数
格式:
修饰符 返回值类型 方法名(数据类型… 变量名){}
这里的变量其实是一个数组
如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个*/
public static void main(String[] args) {
print("a",11,22,33,44);
} public static void print(String s,int...arr) {
System.out.println(s);
for (int i : arr) {
System.out.println(i);
}
} }
数组--集合:
import java.util.Arrays;
import java.util.List; public class Demo4_AsList { public static void main(String[] args) {
//Arrays工具类的asList()方法的使用
// 数组转集合,不能添加,但可以用其它集合中的方法
//数组必须是引用数据类型
String[] arr = {"11","22","33"};
List<String> list = Arrays.asList(arr);
// list.add("a"); //UnsupportedOperationException 不能添加
System.out.println(list);//[11, 22, 33] int[] arr2 = {11,22,33,44};
List<int[]> list2 = Arrays.asList(arr2);
System.out.println(list2);//[[I@15db9742] Integer[] arr3 = {11,22,33,44};
List<Integer> list3 = Arrays.asList(arr3);
System.out.println(list3);//[11, 22, 33, 44] //集合转数组
ArrayList<String> list4 = new ArrayList<>();
list4.add("a");
list4.add("b");
list4.add("c");
list4.add("d"); String[] arr4 = list4.toArray(new String[5]);//指定数组的长度,小于size就会 等于
for (String string : arr4) {
System.out.print(string+" ");//a b c d null
} } }
import java.util.ArrayList; import com.fly.bean.Person; public class Demo3_ArrayList { public static void main(String[] args) {
// 集合嵌套集合
ArrayList<ArrayList<Person>> list = new ArrayList<>();
ArrayList<Person> arrayList = new ArrayList<>();
arrayList.add(new Person("a",1));
arrayList.add(new Person("b",2));
arrayList.add(new Person("c",3)); ArrayList<Person> arrayList2 = new ArrayList<>();
arrayList2.add(new Person("A",11));
arrayList2.add(new Person("B",22));
arrayList2.add(new Person("C",33)); list.add(arrayList);
list.add(arrayList2);
for (ArrayList<Person> list2 : list) {
for (Person person : list2) {
System.out.println(person);
/* Person [name=a, age=1]
Person [name=b, age=2]
Person [name=c, age=3]
Person [name=A, age=11]
Person [name=B, age=22]
Person [name=C, age=33]*/
}
}
}
}
HashSet:
import java.util.HashSet; import com.fly.bean.Person; public class Demo1_Set { public static void main(String[] args) {
HashSet<String> hSet = new HashSet<>(); //Set集合,无索引,不可重复,无序
boolean b1 = hSet.add("a");
boolean b2 = hSet.add("a"); System.out.println(hSet);//[a] 当向set集合中存储重复元素的时候返回为false
System.out.println(b1);//true
System.out.println(b2);//false HashSet<Person> hPersons = new HashSet<>();
hPersons.add(new Person("小明",19));
hPersons.add(new Person("小明",19));
hPersons.add(new Person("李四",19));
hPersons.add(new Person("李四",19));
hPersons.add(new Person("李四",17));
hPersons.add(new Person("张三",17)); System.out.println(hPersons.size());//
System.out.println(hPersons);//[Person [name=小明, age=19], Person [name=李 四, age=19], Person [name=李四, age=17], Person [name=张三, age=17]] } } Person类: public class Person {
private String name;
private int age;
public Person() {
super();
// TODO Auto-generated constructor stub
}
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;
}
//将自定义类的对象存入HadhSet去重,必须重写hashCode()和equals()方法
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() { //只有在hashcode相同时才会执行equals
final int prime = 31;//31是一个质数,这个数不大不小,是2的5次方-1,即2向左 移动5位减一
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) //调用的对象和传入的对象是同一个对象
return true;
if (obj == null) //传入的对象是null
return false;
if (getClass() != obj.getClass()) //判断两个对象对应的字节码文件是否是同一 个字节码
return false;
Person other = (Person) obj; //向下转型
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
} }
LinkedHashSet:
import java.util.LinkedHashSet; public class Demo2_LinkedHashSet { public static void main(String[] args) {
// LinkedHashSet
//底层是链表实现的
//元素唯一
LinkedHashSet<String> linkedHashSet= new LinkedHashSet<>();
linkedHashSet.add("a");
linkedHashSet.add("a");
linkedHashSet.add("b");
linkedHashSet.add("c"); System.out.println(linkedHashSet);//[a, b, c]
} }
import java.util.HashSet;
import java.util.Random; public class Test1 { public static void main(String[] args) {
// 10个1~20的随机数,不重复
Random random = new Random();
HashSet<Integer> hs = new HashSet<>();
while(hs.size()<10) {
hs.add(random.nextInt(20)+1);
}
for (Integer integer : hs) {
System.out.println(integer);
}
} }
TreeSet:
import java.util.TreeSet; import com.fly.bean.Person; public class Demo3_TreeSet { public static void main(String[] args) {
//TreeSet集合可以对对象集合排序,同时保证元素唯一
//底层是二叉树
TreeSet<Integer> ts = new TreeSet<>();
ts.add(3);
ts.add(4);
ts.add(1);
ts.add(2);
ts.add(2);
ts.add(2); System.out.println(ts);//[1, 2, 3, 4] TreeSet<Person> ts2 = new TreeSet<>();
ts2.add(new Person("张三",18));
ts2.add(new Person("李四",19));
ts2.add(new Person("王五",20));
ts2.add(new Person("赵六",21)); System.out.println(ts2); /* public class Person implements Comparable<Person>{ ..... //重写compareTo,返回值决定存储方式
@Override
public int compareTo(Person o) {
return -1; // 负数时返回集合,倒序
// 0 返回集合只有一个元素,正数存储顺序
//按照年龄排
// int num = this.age - o.age;
// return num == 0?this.name.compareTo(o.name):num; }
}*/ } }
比较器:
import java.util.Comparator;
import java.util.TreeSet; public class Demo4_TreeSet { public static void main(String[] args) {
TreeSet<String> treeSet = new TreeSet<>(new CompareByLen());
treeSet.add("ab");
treeSet.add("1234");
treeSet.add("fly");
treeSet.add("qwer"); System.out.println(treeSet);//[ab, fly, 1234, qwer]
} }
class CompareByLen implements Comparator<String>{
//比较器
@Override
public int compare(String o1, String o2) {
// 按照字符串的长度比较
//o2是已有的,o1是新来的
int num = o1.length()-o2.length();
return num==0 ? o1.compareTo(o2) : num;
} }
练习:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet; import javax.naming.ldap.SortControl; public class Test2 { public static void main(String[] args) {
//在一个集合中存储了无序并且重复的字符串,
//定义一个方法,让其有序(字典顺序),而且还不能去除重复
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("absf");
list.add("ccc");
list.add("aaa");
sort(list);
System.out.println(list);//[aaa, aaa, absf, ccc]
} public static void sort(List<String> list) {
TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() { @Override
public int compare(String o1, String o2) {
int num = o1.compareTo(o2);
return num==0 ? 1 : num;
}
});
treeSet.addAll(list);
list.clear();
list.addAll(treeSet);
}
}
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet; public class Test3 { public static void main(String[] args) {
//从键盘接收一个字符串, 程序对其中所有字符进行排序
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = scanner.nextLine(); char[] arr = line.toCharArray();//将字符串转换为字符数组
TreeSet<Character> treeSet = new TreeSet<>(new Comparator<Character>() { @Override
public int compare(Character o1, Character o2) {
int num = o2 - o1;
return num==0 ? 1 : num;
}
});
//遍历字符数组,将每一个字符储存在TreeSet集合中
for (Character character : arr) {
treeSet.add(character);
}
//遍历TreeSet集合
for (Character character : treeSet) {
System.out.println(character);
}
} }