java.util.Collection List与其子类 Set与其子类

时间:2023-03-09 14:56:28
java.util.Collection  List与其子类  Set与其子类
package com.Collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator; public class Study01 {
public static void main(String[] args){
Collection<String> c=new ArrayList<String>();
Collection<String> c2=new ArrayList<String>();
c.add("I");
c.add("am");
c.add("guo"); c2.add("he");
c2.add("ha");
/*System.out.println(c);//增的结果
c.remove("I");
System.out.println(c);//删的结果
c.addAll(c2);
System.out.println(c);//增一个集合所有元素
c.removeAll(c2);
System.out.println(c);//删除另一个集合中存在的元素
c.clear();
System.out.println(c);//clear暴力删除所有
*/
System.out.println(c);
System.out.println(c.contains("am"));//包含?
System.out.println(c2);
System.out.println(c.containsAll(c2));//不包含c2中所有 /*System.out.println(c.retainAll(c2));//取交集,用交集替换原集合的元素。只要改变了集合返回true
System.out.println(c);*/
/*c2.add("am");
System.out.println(c.retainAll(c2));
System.out.println(c);*/ //遍历集合
Object[] objs=c.toArray();
for(int i=0;i<objs.length;i++){
System.out.print(objs[i]+"\t");
}
//
System.out.println();
Iterator<String> it=c.iterator();
while(it.hasNext()){
String o=it.next();
System.out.print(o+"\t");
}
}
}
/*
* 引出集合:
* java是面向对象的语言,对象使用的话需要一个容器装,我们前面有StringBuffer和数组两种容器,但都不太适合。因为StringBuffer存储的是字符串,而数组是不可变长的
* 数组和集合的比较:
* 数组不可变长,一个数组只能存储一种类型,,集合只能存储引用数据类型
* Collection 集合
* 表示一组对象,这些对象也称为collection的元素
* 既然是操作一组对象,所以引出一些方法:
* 增加:
* boolean add(Object obj)
* boolean addAll(Collection c)
* 删除:
* remove(Obj o);
* removeAll(Collection c) 移除与c的交集,移除了一个就返回true
* clear() 删除collection中所有元素
* boolean retainAll(Collection c) 此集合保留与c的交集
* 查找:
* 通过遍历可以实现查找:
* iterator() 返回在此collection上的迭代器
* Object[] toArray() 返回包含此collection中所有元素的数组
* <T> T[] toArray() 返回包含此collection中所有元素的数组,并且数组类型为指定的类型
* 判断集合中是否包含指定元素
* contains(Object o) 如果collection包含指定元素,则返回true
* containsAll(Collection c) 如果包含c中所有的元素则返回true
* 基本方法:
* size() 返回集合大小
* isEmpty() 是否为空
* hashCode()
* equals(Object o)
*
* 关于迭代器:
* 迭代是依托于集合的,它的内部实现其实是在各种集合类中的内部类,个人感觉有点像是集合元素的一种特殊形式的复制或者其他
* 两个方法:
* boolean hasNext()如果仍有元素可以迭代,则返回 true。
* Object next()返回迭代的下一个元素。
*
*
*/
package com.List;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator; public class Study01 {
public static void main(String[] args) {
List<String> l=new ArrayList<String>();
l.add("guo");
l.add("da");
l.add("xia");
System.out.println(l);
l.add(0, "ni");
System.out.println(l); List<String> l2=new ArrayList<String>();
l2.add("hao");
l2.add("ma");
l.addAll(1,l2);
System.out.println(l);
System.out.println(l.get(2));
System.out.println(l.indexOf("guo"));
System.out.println("");
l.set(5,"guo");//set是改变的方法。改变的下标必须拥有元素
System.out.println(l);
System.out.println(l.lastIndexOf("guo")); List<String> l3=l.subList(2, 4);
System.out.println(l3); for(int i=0;i<l.size();i++){
String s= l.get(i);
System.out.print(s+"\t");
} ListIterator<String> it=l.listIterator();
System.out.println();
while(it.hasNext()){
String s= it.next();
System.out.print(s+"\t");
}
System.out.println();
while(it.hasPrevious()){//逆序输出
String s= it.previous();
System.out.print(s+"\t");
} System.out.println();
//在遍历的中途中增加操作
while(it.hasNext()){
String s= it.next();
if(s.equals("ma")){
//ConcurrentModificationException 并发修改异常
//l.add("hi"); 不能在迭代的时候直接使用集合进行修改,但在这里可以使用迭代器的方法进行操作,在该下标的后一位增加。此次迭代器中不会出现
it.add("hi");
}
System.out.print(s+"\t");
}
System.out.println("\n"+l); for(int i=0;i<l.size();i++){
String s= l.get(i);
if(s.equals("ma")){
l.add("haha");//for循环过程中增加,遍历出来所有元素
}
System.out.print(s+"\t");
}
System.out.println("\n"+l);
}
/*
*
* 对并发修改异常就是这两种方式处理:
* 一是使用迭代器对象修改
* 二是使用get()和size()的结合操作
*/
}
/*
* List 有序的collection,也称为序列。允许重复。
* 有序:指的是存进去和取出来的顺序一致
* 存取有序,所以就应该是有下标的说法
*
* 新增方法:
* add(int index Object obj) :将元素插入到集合指定下标的位置,之前的位置和后面的元素全部向后推移一位
* addAll(int index,Collection)
* get(int index) 获取指定索引下的元素
* indexOf(Object obj) 返回指定元素在集合中的下标,不存在则返回-1
* lastIndexOf(Object obj) 返回指定元素在集合中最后一次出现的下标
* remove(int index)
* set(int index,Object obj) 将集合中指定下标的元素更改为obj,返回集合中原有的元素
* subList(int formIndex,int toIndex)和String的substring类似,返回截取版的数组
*
* 两个特有遍历方法:
* listIterator() 返回此列表元素的迭代器,注意,是列表专用
* 这个迭代器的特点:可以实现逆向遍历。
* ListIterator
* add(Object obj)将指定的元素插入列表,插入的位置是当前指针位置
* int nextIndex() 返回对next后续元素调用所返回元素的索引
* boolean hasPrevious() 判断将迭代器指针往前移一位是否存在元素
* previous() 迭代器指针前移一位,返回列表的前一个元素
* int previousIndex()
* remove() 从列表中移除又next或者previous返回的最后一个元素
* set(Object obj) 用指定元素替换next或者previous返回的最后一个元素
*
* ListIterator迭代和使用get()和size()结合迭代是List集合的两个特点遍历
*
*
*
*
*/
package com.ArrayList_LinkedList_Vector;

import java.util.ArrayList;
import java.util.LinkedList; public class Study01 {
public static void main(String[] args) {
ArrayList<String> al=new ArrayList<String>();
al.add("ni");
al.add("hao");
al.add("wo");
al.add("men");
al.add("zai");
System.out.println(al); LinkedList<String> ll=new LinkedList<String>();
ll.add("c");
ll.addFirst("a");
ll.addLast("b");
System.out.println(ll);
System.out.println(ll.peek());
System.out.println(ll.poll());
System.out.println(ll);
}
}
/*
* ArrayList
* 底层数组,线程不同步,效率快,安全低
*
* 构造方法:
* ArrayList() 初始容量为10的空列表
* ArrayList(Collection c) 构造一个包含指定元素的集合的对象
* ArrayList(int initialCapacity) 构造一个具有指定初始化容量的空列表
*
* 新增方法:
* ensureCapacity(int minCapacity) 增加此ArrayList的容量
* //removeRange(int fromIndex,int toIndex) 删除指定索引区间的元素 这个方法在JDK1.6中是受保护的,不知道为什么用不了现在。
* trimToSize() 将此ArrayList实际的容量调整为列表的当前大小
*
*/ /*
* LinkedList
* List接口的链接列表实现。不是同步的 链接链表特点:增删快,查询慢 不同步特点:效率快
* 新增方法:
* addFirst(Object obj)
* addLast(Object obj)
* descendingIterator() 返回以逆向顺序在此双端队列的元素上进行迭代的迭代器
* Object element()获取此列表第一个元素
* offer(Object obj)将指定元素添加到列表的末尾
* offerFirst(E e)
* peek()获取第一个元素
* peekLast()获取最后一个元素
* pool()获取第一个元素同时移除第一个元素
* poolFirst()
* poolLast()
* set()
*
*/ /*
*Vector
* 底层数组,查询快,增删慢 线程安全
* 和ArrayList几乎一样,不写太多
*/ /*
* 三个集合的选择:
* 数组底层的:查询快,增删慢 ArrayList Vector
* 线程安全的:速率慢,安全性高:Vector 反之,安全性较低,速率高:ArrayList
* 链表结构:查询慢,增删快 LinkedList
*
*/
package com.Set;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set; /*
* Set接口
* 实现Collection接口,无序,唯一
* 不是真的无序,是按照一种特殊的算法存储的,但不是11排列这种顺序
*
* HashSet
* 底层是哈希表,哈希表示元素为链表的数组结构
* hashSet唯一,所以添加不进重复元素,观察其源码,发现其底层是hashMap,其add方法和hashCode()和equals()方法有关
* 只有当两个元素的hash值相等,并且equals方法为true的时候才会直接跳过这个添加以保证hashSet集合的唯一性
*
* 可以发现,前面好像是有唯一性,使用对象的时候就失效了,这是为什么呢?
* 因为String对象自动重写了hashCode和equals方法,比较的是值。而你的Student对象的两个方法都没有重写,比较的就
* 是Object对象的hashCode方法得到的值,也就是地址值的特殊表示。所以,你只有将对象的equals和hashCode方法重写后才能
* 使得hashSet的唯一性生效
* 此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
* LinkedHashSet
* 具有可预知的迭代顺序,LinkedHashSet的子类
* 底层是哈希表和链表
* 哈希表保证元素唯一性
* 链表保证元素有序(存储一致)
*/
/*
* 首先比较哈希值是否相同
* 相同: 继续执行equals
* 返回true:元素重复了,不添加
* 返回false:可以添加
* 不同:也可以添加
*/
public class HashSetAndLinkedHashSet {
public static void main(String[] args) {
LinkedHashSet<String> hs=new LinkedHashSet<String>();
hs.add("hello");
hs.add("java");
hs.add("world");
hs.add("java");
hs.add("world"); for(String s:hs){
System.out.println(s);
}
}
public void test01(){
Set<String> s=new HashSet<String>();
s.add("java");
s.add("hello");
s.add("world");
s.add("java");
s.add("hello"); for(String ss:s){
System.out.println(ss);
} Set<Student> s1=new HashSet<Student>();
s1.add(new Student("林青霞",27));
s1.add(new Student("范冰冰",30));
s1.add(new Student("林青霞",27));
s1.add(new Student("柳岩",25));
s1.add(new Student("林青霞",27)); for(Student ss:s1){
System.out.println(ss);
}
}
} package com.Set; public class Student implements Comparable<Student>{
private String name;
private int 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;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
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)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) 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;
}
public Student() {
super();
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
} @Override
public int compareTo(Student o) {
//两个Student对象的比较方法
//我这里定义它先根据年龄比较,然后根据姓名比较 if(this.equals(o)){
return 0;
}else if(this.getAge()==o.getAge()){
return this.getName().compareTo(o.getName());
}else{
return this.getAge()-o.getAge();
}
} } package com.Set; import java.util.Comparator;
import java.util.TreeSet; /*
* TreeSet:能够对元素按照某种规律排序
* TreeSet的排序方式和它的比较方式有关
*
* 底层是红黑树结构!
*
* 排序有两种:
* A:自然排序
* B:比较器排序
*
* 构造方法:
* TreeSet() 构造新的空set,根据自然顺序进行排序
* TreeSet(Comparator<? extends E> o) 构建一个空的TreeSet,它根据比较器进行排序
* TreeSet集合的特点:
* 排序和唯一
* 唯一:根据比较的值是否为0
* 排序:数的存储方式和取出方式
*
* 自然排序接口:Comparable 在基本数据类型和常用类型都有它的实现,它表现在类型的compareTo方法上:
* Number型比较的是数值的大小,String比较的是内容的哈希吗,boolean类型真比假为正,假比真为负,其他为0,char类型比较的是Ascill码
* 如果你使用的是自定义对象类型,就必须实现Comparable接口,才能使用自然排序。
* 自然排序,就是依据对象的compareTo方法进行排序
*
* 比较器排序
* 什么是比较器?
* 比较器是一个用来比较两个同类型对象的对象,比较器实现了Comparator接口,在compare方法中确定如何比较或者说是比较结果。
*
* 使用比较器就是在构造方法中加入比较器。
*
* 使用比较器与自然排序相比:
* 自然排序的比较方式是定义在对象里的,所以每一个同类型的对象的比较方法都是确定的。而比较器是独立的一个对象,在需要这样比较的时候调用特定的比较器就好。
*/
public class TreeSetStudy {
public static void main(String[] args) {
//我们前面使用了自然排序,那么怎么使用比较器排序呢?
TreeSet<Student> ts=new TreeSet<Student>(new comparator02());
ts.add(new Student("林青霞",27));
ts.add(new Student("刘亦菲",18));
ts.add(new Student("苏有朋",30));
ts.add(new Student("刘诗诗",18)); for(Student i:ts){
System.out.println(i);
}
}
public void test01(){
TreeSet<Integer> ts=new TreeSet<Integer>();
ts.add(18);
ts.add(28);
ts.add(22);
ts.add(18);
ts.add(19); for(int i:ts){
System.out.println(i);
}
} public void test02(){
//自然排序
TreeSet<String> ts=new TreeSet<String>();
ts.add("hi");
ts.add("nice");
ts.add("to");
ts.add("meet");
ts.add("you"); for(String s:ts){
System.out.println(s);
}
} public void test03(){
//这样报错:com.Set.Student cannot be cast to java.lang.Comparable
//因为这样默认使用的是自然排序,但是Student并没有实现Comparable接口,没有自然比较方法,接下来我们让Student实现Comparable接口试试
TreeSet<Student> ts=new TreeSet<Student>();
ts.add(new Student("林青霞",27));
ts.add(new Student("刘亦菲",18));
ts.add(new Student("苏有朋",30));
ts.add(new Student("刘诗诗",18)); for(Student i:ts){
System.out.println(i);
}
} public void test04(){
TreeSet<Integer> ts=new TreeSet<Integer>(new comparator01());
ts.add(18);
ts.add(28);
ts.add(22);
ts.add(18);
ts.add(19); for(int i:ts){
System.out.println(i);
}
}
}
class comparator01 implements Comparator<Integer>{ @Override
public int compare(Integer o1, Integer o2) {
int i=o2-o1;
return i;
} } class comparator02 implements Comparator<Student>{ @Override
public int compare(Student o1, Student o2) {
if(o1.getAge()!=o2.getAge()){
return o2.getAge()-o1.getAge();//年龄从大到小排序
}else{
return o1.getName().compareTo(o2.getName());
}
} } package com.Set; import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet; /*
* ctrl+ shift+ o 自动导包
* alt+ shift +s+o 有参构造
* alt+ shift +s+c 无参构造
* alt+ shift +s+r 封装
*/
public class TreeSetDemo {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//内部类实现比较
TreeSet<Student01> ts=new TreeSet<Student01>(new Comparator<Student01>(){ @Override
public int compare(Student01 o1, Student01 o2) {
//总分从高到低
int num=o2.getSum()-o1.getSum();
//总分相同的语文不一定相同
int num2=num==0?o1.getChinese()-o2.getChinese():num;
//数学不一定相同
int num3=num2==0?o1.getMath()-o2.getMath():num2;
//英语不一定相同
int num4=num3==0?o1.getEnglish()-o2.getEnglish():num3;
//姓名不一定相同
int num5=num4==0?o1.getName().compareTo(o2.getName()):num4;
return num5;
}
}); for(int x=1;x<=5;x++){
System.out.println("请输入第"+x+"个学生的姓名:");
String name=sc.nextLine();
System.out.println("请输入第"+x+"个学生的语文成绩:");
String chineseString=sc.nextLine();
System.out.println("请输入第"+x+"个学生的数学成绩:");
String mathString=sc.nextLine();
System.out.println("请输入第"+x+"个学生的英语成绩:");
String englishString=sc.nextLine(); Student01 s=new Student01();
s.setName(name);
s.setChinese(Integer.parseInt(chineseString));
s.setMath(Integer.parseInt(mathString));
s.setEnglish(Integer.parseInt(englishString));
ts.add(s);
}
System.out.println("学生信息录入完毕");
System.out.println("学生信息从高到低顺序如下:");
System.out.println("姓名\t语文成绩\t数学成绩\t英语成绩"); for(Student01 s:ts){
System.out.println(s.getName()+"\t"+s.getChinese()+"\t"+s.getMath()+"\t"+s.getEnglish());
}
}
}
class Student01{
private String name;
private int chinese;
private int math;
private int english;
public Student01(String name, int chinese, int math, int english) {
super();
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}
public Student01() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
} public int getSum(){
return getChinese()+getMath()+getEnglish();
} }