Java集合
import java.time.DayOfWeek;
import java.util.*;
import java.util.function.Consumer;
//Collection是除Map外所有集合类的根接口,是一个interface,继承Iterable接口
//List:一种有序列表的集合,例如,按索引排列的Student的List; //有序列表的集合
//Set:一种保证没有重复元素的集合,例如,所有无重复名称的Student的Set;//没有重复元素的集合,没有顺序
//Map:一种通过键值(key-value)查找的映射表集合,例如,根据Student的name查找对应Student的Map。 //key,value,其中key不重复
public class JavaCollection {
// 1。list,有序列表
// 和数组一样,添加,删除元素,如果是中间的元素,需要移动元素。使用ArrayList,就自动帮我们做了。
//我们考察List<E>接口,可以看到几个主要的接口方法:
//
// 在末尾添加一个元素:boolean add(E e)
// 在指定索引添加一个元素:boolean add(int index, E e)
// 删除指定索引的元素:E remove(int index)
// 删除某个元素:boolean remove(Object e)
// 获取指定索引的元素:E get(int index)
// 获取链表大小(包含元素的个数):int size()
// 一个是ArrayList,还有一个是LinkedList
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(1);
System.out.println(linkedList.get(0));
System.out.println(linkedList.pop());
// System.out.println(linkedList.pop());
ArrayList list = new ArrayList();
list.add(1);
list.add(2);
Object[] array = list.stream().toArray();
for (Object obj:array){
System.out.println(obj);
}
// 单独使用List
List<String> list1 = List.of("apple","pear","banana");
list1.contains("apple");
// list1.add("good"); // not supported, because list.of return a immutable object.
System.out.println(list1);
List<Integer> list11 = List.of(12, 34, 56);
// 通过new Interger[5]来生成指定5个数量的数组,然后会把list的数据放进去
// then array1 is free to modify, no reference indict to any elements in it.
Integer[] array1 = list11.toArray(new Integer[5]);
for (Integer n : array1) {
System.out.println(n);
}
// test for equals method.
List<String> list_string = List.of("A","B","C");
System.out.println(list_string.contains("A"));
System.out.println(list_string.indexOf("A"));
System.out.println(list_string.indexOf("BC"));
System.out.println(list_string.contains(new String("C"))); // true or false?
System.out.println(list_string.indexOf(new String("C"))); // 2 or -1?
//contains 是调用对象的equals方法对比的,
//如果放入了new Person("Bob"),但是用另一个new Person("Bob")查询不到,原因就是Person类没有覆写equals()方法。
class Person{
public String firstname;
public String lastname;
public int age;
Person(String firstname,String lastname,int age){
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Person){
Person p = (Person) obj;
return Objects.equals(this.firstname,p.firstname) &&Objects.equals(this.lastname,p.lastname) && p.age==this.age;
}
return false;
}
@Override
public int hashCode() {
// int h =0;
// h = 31*h + this.firstname.hashCode();
// h = 31*h + this.lastname.hashCode();
// h = 31*h + age;
// return h;
// if firstname == null will result error
// so we use Objects(utils) .hash
// the passed variable must be used in equals method.
return Objects.hash(firstname,lastname,age);
}
// 因此,我们总结一下equals()方法的正确编写方法:
//
// 先确定实例“相等”的逻辑,即哪些字段相等,就认为实例相等;
// 用instanceof判断传入的待比较的Object是不是当前类型,如果是,继续比较,否则,返回false;
// 对引用类型用Objects.equals()比较,对基本类型直接用==比较。
// 使用Objects.equals()比较两个引用类型是否相等的目的是省去了判断null的麻烦。两个引用类型都是null时它们也是相等的。
//
// 如果不调用List的contains()、indexOf()这些方法,那么放入的元素就不需要实现equals()方法。
}
List<Person> persolist = List.of(new Person("aaa","bbb",111));
System.out.println(persolist.contains(new Person("aaa","bbb",111)));
Map<DayOfWeek, String> map = new EnumMap<>(DayOfWeek.class);
map.put(DayOfWeek.MONDAY, "星期一");
map.put(DayOfWeek.TUESDAY, "星期二");
map.put(DayOfWeek.WEDNESDAY, "星期三");
map.put(DayOfWeek.THURSDAY, "星期四");
map.put(DayOfWeek.FRIDAY, "星期五");
map.put(DayOfWeek.SATURDAY, "星期六");
map.put(DayOfWeek.SUNDAY, "星期日");
System.out.println(map);
System.out.println(map.get(DayOfWeek.MONDAY));
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("pear");
set.add("orange");
for (String s : set) {
System.out.println(s);
}
Set<String> set1 = new TreeSet<>();
set1.add("apple");
set1.add("banana");
set1.add("pear");
set1.add("orange");
for (String s : set1) {
System.out.println(s);
}
// Queue 是个接口,表示单端队列,Deque是一个接口,表示双端队列
Deque deque = new LinkedList();
//LinkedList即实现了List接口,又实现了Queue接口,
// 但是,在使用的时候,如果我们把它当作List,就获取List的引用,如果我们把它当作Queue,就获取Queue的引用:
LinkedList ls = new LinkedList();
// 始终按照面向抽象编程的原则编写代码,可以大大提高代码的质量。
// 还有一个优先级队列,比如VIP充了钱,他排队就可以到前面了
//PriorityQueue和Queue的区别在于,它的出队顺序与元素的优先级有关,
// 对PriorityQueue调用remove()或poll()方法,返回的总是优先级最高的元素。
// 因此,放入PriorityQueue的元素,必须实现Comparable接口,PriorityQueue会根据元素的排序顺序决定出队的优先级。
Queue prioriqueue = new PriorityQueue<Person>(new Comparator<>() {
@Override
public int compare(Person o1, Person o2) {
if(o1.age == o2.age){
return 0;
}
return o1.age>o2.age?-1:1;
}
});
Person p1 = new Person("1","2",15);
Person p2 = new Person("1","2",16);
Person p3 = new Person("1","2",17);
prioriqueue.offer(p1);
prioriqueue.offer(p3);
prioriqueue.offer(p2);
System.out.println("---------------");
System.out.println(((Person)prioriqueue.poll()).age);
System.out.println(((Person)prioriqueue.poll()).age);
System.out.println(((Person)prioriqueue.poll()).age);
System.out.println("---------------");
// stack 栈
Stack stack = new Stack<>();
stack.add("1");
stack.add(2);
stack.add(new Person("jian","ge",1));
for (Object obj:
stack) {
if (obj instanceof Person){
obj = (Person) obj;
}
System.out.println(obj);
}
// Iterator
ReversList list_res = new ReversList();
list_res.add(1);
list_res.add(3);
list_res.add(2);
for(Iterator<Integer> iterator1 = list_res.iterator();iterator1.hasNext();){
int s = iterator1.next();
System.out.println(s);
}
// Collections 不是 Collection类,这个Collections提供了很多集合操作的工具方法,都是静态函数。
//addAll()方法可以给一个Collection类型的集合添加若干元素。
// 因为方法签名是Collection,所以我们可以传入List,Set等各种集合类型。
// Collections.addAll()
// Collections提供了一系列方法来创建空集合:
//
// 创建空List:List<T> emptyList()
// 创建空Map:Map<K, V> emptyMap()
// 创建空Set:Set<T> emptySet()
// 此外,也可以用各个集合接口提供的of(T...)方法创建空集合。例如,以下创建空List的两个方法是等价的:
//
// List<String> list1 = List.of();
// List<String> list2 = Collections.emptyList();
// 要注意到返回的空集合是不可变集合,无法向其中添加或删除元素。
System.out.println("-----------------");
ArrayList<Integer> my_listr = new ArrayList<>(List.of(5,3,2,7,6));
my_listr.add(4);
Collections.sort(my_listr);
for (int i:
my_listr) {
System.out.println(i);
}
System.out.println("-----------------");
Collections.shuffle(my_listr);
for (int i:
my_listr) {
System.out.println(i);
}
System.out.println("-----------------");
List list_unmodify = Collections.unmodifiableList(my_listr);
// list_unmodify.add(1); //will result error.
// if not delete the original reference, the original reference may modify the elements in the list.
my_listr = null;
// my_listr.add(1);
for (Object i:
list_unmodify) {
System.out.println(i);
}
}
}
//一个自定义集合或者数据类型要能够迭代的话,需要实现Iterable接口,
class ReversList<T> implements Iterable {
private List<T> list = new ArrayList<>();
public void add(T t){
list.add(t);
}
// 这个返回Iterable的函数是必须要实现的。
@Override
public Iterator iterator() {
return new ReversIterator(list.size());
}
class ReversIterator implements Iterator<T>{
int size;
int index = -1;
ReversIterator(int size){
this.size = size;
}
@Override
public boolean hasNext() {
return size>0;
}
@Override
public T next() {
size--;
index++;
return ReversList.this.list.get(index);
}
}
// 这两个函数在接口中是有默认实现的
// @Override
// public void forEach(Consumer action) {
// Iterable.super.forEach(action);
// }
//
// @Override
// public Spliterator spliterator() {
// return Iterable.super.spliterator();
// }
}
//最后,Java访问集合总是通过统一的方式——迭代器(Iterator)来实现,它最明显的好处在于无需知道集合内部元素是按什么方式存储的。
//由于Java的集合设计非常久远,中间经历过大规模改进,我们要注意到有一小部分集合类是遗留类,不应该继续使用:
// Hashtable:一种线程安全的Map实现;
// Vector:一种线程安全的List实现;
// Stack:基于Vector实现的LIFO的栈。
//还有一小部分接口是遗留接口,也不应该继续使用:
// Enumeration<E>:已被Iterator<E>取代。
//Java的集合类定义在java.util包中,支持泛型,主要提供了3种集合类,包括List,Set和Map。
// Java集合使用统一的Iterator遍历,尽量不要使用遗留接口。