集合类特点:提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变
这里需要回顾一下,因为数组和字符串一旦创建,就不可改变,需要区分一下
import java.util.ArrayList; import java.util.Collection; public class CollectionDemo { public static void main(String[] args) { Collection<String> c = new ArrayList<>(); c.add("Hello"); c.add("World"); c.add("java"); System.out.println(c); // 集合常用方法 // 长度size System.out.println(c.size()); // 添加add,上文已使用 // 移除remove c.remove("hello"); boolean hello = c.remove("Hello"); System.out.println(hello); System.out.println(c); // 包含 boolean world = c.contains("World"); System.out.println(world); // 判空 boolean empty = c.isEmpty(); System.out.println(empty); // 清空 c.clear(); System.out.println(c); } }
[Hello, World, java] 3 true [World, java] true false []
用完之后发现这种多态方式使用Collection
并不好用,不如直接使用ArrayList
,而且ArrayList
常用的5个方法更好用:add
、get
、remove
、set
、size
如果想对Collection
进行遍历,需要使用迭代器
Iterator是集合的专用遍历方式,Collection可以用,ArrayList之类的也可以用
常用3个方法:next
、hasNext
、remove
// Iterator的使用 import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class IteratorDemo { public static void main(String[] args) { Collection<String> c = new ArrayList<>(); c.add("Hello"); c.add("World"); c.add("Java"); c.add("100"); // c.add("101"); Iterator<String> iterator = c.iterator(); while(iterator.hasNext()) { String s = iterator.next(); // if(s.equals("100")){ iterator.remove(); System.out.println(s); // iterator.add("Java"); } // System.out.println(iterator.next()); } System.out.println(c); } }
要注意,Iterator没有add方法,强行使用会导致并发修改异常
有序集合,可重复
并发修改异常:迭代器遍历过程中,通过集合对象修改了集合中元素长度,造成迭代器获取元素中判断预期修改值和实际修改值不一致。解决:使用for循环
import java.util.ArrayList; import java.util.List; import java.util.ListIterator; public class ListIteratorDemo { public static void main(String[] args) { List<String> str = new ArrayList<>(); str.add("Hello"); str.add("World"); str.add("Java"); ListIterator<String> listIterator = str.listIterator(); /* while(listIterator.hasPrevious()){ // System.out.println(listIterator.previousIndex()); // System.out.println(listIterator.previous()); String previous = listIterator.previous(); System.out.println(previous); } */ while(listIterator.hasNext()){ String next = listIterator.next(); if(next.equals("Java")){ listIterator.add("JavaEE"); } } while(listIterator.hasPrevious()){ System.out.println(listIterator.previousIndex()); // System.out.println(listIterator.previous()); String previous = listIterator.previous(); System.out.println(previous); } } }
3 JavaEE 2 Java 1 World 0 Hello
ListIterator可以使用add方法,并且可以查看迭代器的索引
for(元素数据类型变量名:数组或者Collection集合){//使用变量}
public class ForDemo { public static void main(String[] args) { int [] arr = {1,2,3,4,5}; for(int i:arr){ System.out.println(i); } } }
数据进入栈模型的过程称为:压/进栈,反之为弹/出栈
栈是先进后出的模型
入队/出队
队列是先进先出的模型
查询数据通过索引定位,查询效率高
删除和添加效率低
增删快,查询慢
ArrayList是List接口的可调整大小的数组实现,数组特点是查询快,增删慢
LinkList是双链表实现List和Deque接口,查询慢,增删快
常用方法:addFirst
、addLast
、getFirst
、getLast
、removeFirst
、removeLast
居然还可以在指定位置插入元素
add(int index, E element)
在列表中指定的位置上插入指定的元素。不包含重复元素的集合,且没有带索引的方法,不能使用普通for循环遍历
对集合的迭代顺序不作任何保证
hashCode方法
,默认情况下,不同对象的hash值不同
// Student类 public class Student { private int age; public Student() { } public Student(int age) { this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
// 测试类 import java.util.HashSet; import java.util.Set; public class My_Hash { public static void main(String[] args) { Set<String> s1 = new HashSet<>(); s1.add("java"); Set<String> s2 = new HashSet<>(); s2.add("java"); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println("--------"); Student s3 = new Student(18); Student s4 = new Student(18); System.out.println(s3.hashCode()); System.out.println(s4.hashCode()); } }
3254818 3254818 -------- 1324119927 990368553
但是可以在原来的类中重写hashCode方法,这样就可以返回指定hash值
如在上述学生类
中重写hashCode方法如下
@Override public int hashCode(){ return age; // return 0; }
这样返回的hash值就都为自己创建对象的age值
有哈希表和链表实现的Set接口,具有可预测的迭代次序
由链表保证元素有序,也就是说元素的存储和取出的顺序是一致的,这点和HashSet不同
由哈希表保证元素唯一性
元素按照一定的规则进行排序,无参构造方法按照自然顺序排序,带参构造方法按照指定规则排序
要进行自然排序,需Comparable
或者Comparator
首先看一下TreeSet对Integer进行自然排序
import java.util.TreeSet; public class Demo { public static void main(String[] args) { TreeSet<Integer> ts = new TreeSet<>(); ts.add(5); ts.add(10); ts.add(1); ts.add(7); ts.add(20); for(int i:ts){ System.out.println(i); } } }
1 5 7 10 20
这是因为Integer实现了Comparable接口,不能想当然认为其他类也实现了
public final class Integer extends Number implements Comparable<Integer>
接下来对一般类实现自然排序
// 学生类 public class Student implements Comparable{ private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public Student() { } 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 "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Object o) { // return 0; return 1; } }
// 测试类 public class Demo { public static void main(String[] args) { TreeSet<Student> s = new TreeSet<>(); Student s1 = new Student("linqingxia",18); Student s2 = new Student("zhangmanyu",48); Student s3 = new Student("wangzuxian",38); Student s4 = new Student("zhangmin",28); s.add(s1); s.add(s2); s.add(s3); s.add(s4); for(Student st:s){ System.out.println(st); } } }
继承Comparale,再重写CompareTo方法
int compareTo(T o) ``` 将此对象与指定的对象进行比较,以。返回一个负整数、零或一个正整数,因为这个对象小于、等于或大于指定的对象。
如果想要按照年龄进行排序,则需要把CompareTo进行如下改写
public class Student implements Comparable<Student>{ private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public Student() { } 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 "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Student s) { // return 0; int num1 = this.age - s.age; int num2 = num1 == 0?this.name.compareTo(s.name):num1; return num2; } }
import java.util.TreeSet; public class Demo { public static void main(String[] args) { TreeSet<Student> s = new TreeSet<>(); Student s1 = new Student("linqingxia",18); Student s2 = new Student("zhangmanyu",48); Student s3 = new Student("wangzuxian",38); Student s4 = new Student("zhangmin",28); Student s5 = new Student("qiushuzhen",28); s.add(s1); s.add(s2); s.add(s3); s.add(s4); s.add(s5); for(Student st:s){ System.out.println(st); } } }
TreeSet结合存储自定义对象时,带参构造方法使用比较器排序对元素进行排序
同样,也可以让类继承Compareble,然后重写CompareTo来实现
上例中implements Compareble<Student>
是因为测试类中使用的是泛型
为了简化,就不写get和set方法
// 学生类 public class Student implements Comparable<Student>{ private String name; private int mathScore; private int chinesScore; private int englishScore; public int setTotalScore(){ return mathScore+chinesScore+englishScore; } public Student(String name, int mathScore, int chinesScore, int englishScore) { this.name = name; this.mathScore = mathScore; this.chinesScore = chinesScore; this.englishScore = englishScore; } public Student() { } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", mathScore=" + mathScore + ", chinesScore=" + chinesScore + ", englishScore=" + englishScore + ", totalScore=" + setTotalScore() + '}'; } @Override public int compareTo(Student student) { int num1 = student.setTotalScore() - this.setTotalScore(); int num2 = num1 == 0?student.mathScore-this.mathScore:num1; int num3 = num2 == 0?student.chinesScore-this.chinesScore:num2; int num4 = num3 == 0?student.englishScore-this.englishScore:num3; int num5 = num4 == 0?student.name.compareTo(this.name):num4; return num5; } }
// 测试类 import java.util.TreeSet; public class Demo { public static void main(String[] args) { TreeSet<Student> ts = new TreeSet<>(); Student s1 = new Student("赵",99,98,99); Student s2 = new Student("钱",98,99,100); Student s3 = new Student("孙",99,98,100); Student s4 = new Student("李",100,99,98); ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); for(Student s:ts){ System.out.println(s); } } }
包装类如Integer和String是实现了Compareble的,所以可以直接使用CompareTo方法