java我之集合观
什么是集合:
对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能
和数组的区别:
- 数组长度固定,集合不固定
- 数组存储:基本类型(栈)和引用类型(堆里),集合只是引用类型(堆)
- 在java.util 包里
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ugfFYIPm-1632559021505)(C:\Users\74771\AppData\Roaming\Typora\typora-user-images\1632314555913.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EGT9aZCw-1632559021515)(C:\Users\74771\AppData\Roaming\Typora\typora-user-images\1632380753081.png)]
collection的使用
public static void main(String[] args) {
//创建集合
Collection collection = new ArrayList();
//1.添加元素
collection.add("西瓜");
collection.add("梨");
collection.add("桃子");
System.out.println(collection.size());
System.out.println(collection);
//删除元素//
collection.remove("苹果");//
collection.clear(); //
//遍历,只能用加强for循环,因为collection没有下标
for(Object object:collection) {
System.out.println(object);
}
//用迭代器遍历,(有点像两个指针)专门
//.hasNext();有没有下一个元素
//next();获取下一个元素
//.remove();删除当前元素
Iterator it = collection.iterator();
while(it.hasNext()) {
String s= (String)it.next();
System.out.println(s);
it.remove(); //不能用collection的 remove }
//判断
System.out.println(collection.contains("西瓜")); System.out.println(collection.isEmpty()); }
package jiheCollection.collection;
import InnerClass.inClass.bigDecimal.Student;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class collectionTest {
public static void main(String[] args) {
Collection collection = new ArrayList();
Student s1 = new Student("张三",18);
Student s2 = new Student("lisi",16);
collection.add(s1);
collection.add(s2);
System.out.println(collection.size());
//为什么打印出来是这个样子??未完待续 已经解决了,原是自己创建的class 太多了,下回注意!
System.out.println(collection.toString());
System.out.println("=================");
//删除
collection.remove(s1);
//删除不了,等于创建一个新的,再删除
collection.remove(new Student("张三",33));
System.out.println(collection.size());
System.out.println("=================");
for(Object obj:collection)
{
Student s = (Student)obj;
System.out.println(s);
}
System.out.println("=================");
Iterator it = collection.iterator();
while(it.hasNext()){
Student s5 = (Student) it.next();
System.out.println(s5);
}
//判断
System.out.println(list.contains("玉碗成来琥珀光"));
System.out.println(list.isEmpty());
//获取信息
System.out.println(list.indexOf("玉碗成来琥珀光"));
}}
List的使用
public static void main(String[] args) {
List list = new ArrayList();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
//删除操作,不能只是根据下标删除
list.remove(1);
//根据数据来删除,需要转换一下类型
list.remove((Object) 20);
//补充方法subList,返回子集合,含头不含尾
List subList = list.subList(1, 3);
System.out.println(subList);
public static void main(String[] args) {
List list = new ArrayList();
list.add("兰陵美酒郁金香");
list.add("玉碗成来琥珀光");
System.out.println(list.size());
System.out.println(list);
//下标删除的方法,比较方便
list.remove(0);
System.out.println(list);
//遍历
//1.按下标,
for(int i=0;i<list.size();i++){
System.out.println(list.get(i)); }
System.out.println("==============");
//2.增强for循环
for(Object object:list){
System.out.println(object); }
System.out.println("==============");
//使用迭代器
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next()); }
System.out.println("==============");
//使用列表迭代器 List 特有的
ListIterator lit = list.listIterator();
while(lit.hasNext()) {
System.out.println(lit.nextIndex()+":"+lit.next()); }
//从后往前遍历
while(lit.hasPrevious()) {
System.out.println(lit.previousIndex()+":"+lit.previous()); }
ArrayList的使用
ListIterator和Iterator 两个迭代器
ArrayList arrayList = new ArrayList();
Student s1 = new Student("王维",18);
Student s2 = new Student("杜甫",68);
Student s3 = new Student("姜夔",20);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
System.out.println(arrayList);
//用 new 时 删不了,删除元素时,只有重写了equals方法,才可以
arrayList.remove(1);
arrayList.remove(new Student("王维",18)); System.out.println(arrayList);
//遍历
Iterator it = arrayList.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
System.out.println("============");
ListIterator lit = arrayList.listIterator();
while(lit.hasNext()){
System.out.println(lit.next());
}
while(lit.hasPrevious()){
System.out.println(lit.previous());
}
//判断
System.out.println(arrayList.contains(new Student("杜甫",68)));
//查找
System.out.println(arrayList.indexOf(new Student("姜夔",20)));
关于重写equals的方法
public boolean equals(Object obj) {
//判断是不是同一个对象
if(this == obj) {
return true;
}
//判断是否为空
if (obj == null) {
return false;
}
//判断是否是Student类型
if (obj instanceof Student){
Student s = (Student)obj;
//比较属性
if (this.name.equals(s.getName())&&this.age==s.getAge()) {
return true;
}
}
return false;
}
ArrayList 源码分析
DEFAULT_CAPACITY = 10;默认容量
如果没有add任何元素,容量为0,添加一个后为10,以后每次扩大原来的1.5倍。
Vector的使用
public class vector {
public static void main(String[] args) {
Vector vector = new Vector();
vector.add("苹果");
vector.add("香蕉");
vector.add("梨");
//
vector.remove(2);
/vector.remove("苹果");
System.out.println(vector);
//遍历,枚举类型
Enumeration en = vector.elements();
while (en.hasMoreElements()){
String s = (String)en.nextElement();
System.out.println(s);
}
//判断
System.out.println(vector.contains("苹果"));
System.out.println(vector.isEmpty()); }
LinkedList的使用
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
Student s1 = new Student("张三",19);
Student s2 = new Student("李四",76);
Student s3 = new Student("王五",4);
linkedList.add(s1);
linkedList.add(s3);
linkedList.add(s2);
System.out.println(linkedList.toString());
//删除//
linkedList.remove(s1);//
linkedList.remove(new Student("张三",19));
//遍历
for (int i=0;i<linkedList.size();i++) {
System.out.println(linkedList.get(i));
}
for (Object o:linkedList){
System.out.println(o);
}
Iterator it = linkedList.listIterator();
while(it.hasNext()){
System.out.println(it.next()); }
泛型类的使用
- 泛型只能是引用类型(int 是基本类型,不行,要用Integer)
- 不同泛型对象不能相互复制
public class myGeneric <T>{
T t; //由于是泛型类,不知道确定的类型,所以不用 new
public void show(T t){
System.out.println(t);
}
public T ex(T t){
return t;
}
public static void main(String[] args) {
myGeneric<String> myGeneric1 = new myGeneric();
myGeneric1.t = "三山半落青天外";
myGeneric1.show(myGeneric1.t);
myGeneric1.ex(myGeneric1.t);
myGeneric<Integer> myGeneric2 = new myGeneric<>();
myGeneric2.t = 12345;
myGeneric2.show(myGeneric2.t);}
泛型接口的使用
//先定义借口
//在另一个类里impl 这个借口
//然后在第三个类里实现,不容易
public interface Interface<T> {
//String s= "你好";
//不能直接写 T t;
//借口肯定是用来实现方法,所以写方法
T server(T t);
}
//只能传String 类型的
public class interfaceImpl implements Interface<String> {
@Override
public String server(String s) {
System.out.println(s);
return null;
}
}
//都变为T 泛型类,随便传
public class interfaceImpl<T> implements Interface<T> {
@Override
public T server(T t){
System.out.println(t);
return t; }
}
//经本认梳理,得出可穿 字符串和数据类型的 程序,简单 一程序多实现,漂亮
//泛型类 nb
public class interfaceImpl<T> implements Interface<T> {
@Override
public T server(T t) {
System.out.println(t);
return null;
}
public static void main(String[] args) {
interfaceImpl imp = new interfaceImpl() ;
imp.server(12233);
imp.server("雅俗共赏");
}
泛型方法的使用
public class genericMain {
//觉得方法和interfa 功能差不多,甚至方法更简单一些
public <T> T show(T t){
System.out.println(t);
return t;
}
泛型集合
public static void main(String[] args) {
ArrayList<> arrayList = new ArrayList();
arrayList.add("山水之间");
arrayList.add(1111);
for (Object o:arrayList){
String str = (String) o;
System.out.println(str); }
}
//下面这个在遍历的时候能够很好的做到 类型转换
public static void main(String[] args) {
ArrayList<String > arrayList = new ArrayList();
arrayList.add("山水之间");
// arrayList.add(1111);
for (String o:arrayList){
String str = (String) o;
System.out.println(str);
}
Set的基本操作
注意其与List的不同,无序,无下标,不可重复
public class setBase {
public static void main(String[] args) {
Set set = new HashSet();
set.add("红杏枝头春意闹");
set.add("一行白鹭上青天");
System.out.println(set);
//遍历
//增强for循环
for(Object o:set) {
System.out.println(o);
}
//使用迭代器
Iterator it = set.iterator();
while(it.hasNext()){ System.out.println(it.next()); } }
HashSet存储方式
哈希表:数组 + 链表 如同
当链表长的时候,就自动转变为树
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HN5hRqsU-1632559021522)(C:\Users\74771\AppData\Roaming\Typora\typora-user-images\1632477646279.png)]
存储过程
- 根据hashCode 计算保存的位置,如果此位置为空,则直接保存,否则执行第二步
- 再执行equals方法,如果equals方法为 true ,则认为是重复,否则,形成链表。
hashCode方法里面有一个质数 31
有这样一个表达式
31 * i = (i<<5)- i
public static void main(String[] args) {
HashSet<Person> hashSet = new HashSet();
Person p1 = new Person("李白",22);
Person p2 = new Person("杜甫",56);
Person p3 = new Person("王维",18);
hashSet.add(p1);
hashSet.add(p2);
hashSet.add(p3);
//一旦重写hashCode 和equals方法就加不进去了,idea自带重写
hashSet.add( new Person("王维",18));
//重写后hashCode 和equals方法后可以 删除 /
hashSet.remove( new Person("李白",22));
//遍历
System.out.println(hashSet.size());
for(Person o:hashSet){
System.out.println(o);
}
//迭代器
Iterator it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
// 关于重写的Person
public class Person {
private String name;
private int age;
public Person(String name, int age) {
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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return true;
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
treeSet的使用
- 使用TreeSet保存数据
- 存储结构:红黑树
- 要求:元素必须实现Comparable接口
//要先implement 接口 Comparer,构建方法,比较谁大谁小,才能摆列出二叉树
@Override
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.getName());
int n2 = this.age-o.getAge();
return n1==0? n2:n1;
}
public static void main(String[] args) {
TreeSet treeSet = new TreeSet();
//使用TreeSet保存数据
//存储结构:红黑树
//要求:元素必须实现Comparable接口
Person p1 = new Person("ee",22);
Person p2 = new Person("aa",56);
Person p3 = new Person("bb",18);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
System.out.println(treeSet);
Comparator
有了比较器就不用实现接口了
如果是 返回值是O,则相等,按正负安插二叉树左右
//开头就是匿名内部类
public static void main(String[] args) {
TreeSet<Person> treeSet = new TreeSet(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1 = o1.getAge() - o2.getAge();
int n2 = o1.getName().compareTo(o2.getName());
return n1==0?n2:n1; }
});
Person p1 = new Person("ee",22);
Person p2 = new Person("aa",56);
Person p3 = new Person("bb",18);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
System.out.println(treeSet);}
TreeSet 比较字符串长度的返回方法
//也是匿名内部类
public static void main(String[] args) {
TreeSet<Person> treeSet = new TreeSet(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1 = o1.getName().length() - o2.getName().length();
int n2 = o1.getName().compareTo(o2.getName());
return n1==0?n2:n1; } });
Map 集合
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ao71GTDu-1632559021527)(C:\Users\74771\AppData\Roaming\Typora\typora-user-images\1632533864655.png)]
Map 的遍历
hashMap是哈希表
public class mapBase {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
//添加元素
map.put("李清照","莫道不消魂");
map.put("马致远","古道西风瘦马");
map.put("王维","大漠孤烟直");
System.out.println(map.values());
System.out.println(map);
System.out.println(map.remove("马致远"));
System.out.println("================");
//遍历
//只遍历一种值
for(String o:map.keySet()){
System.out.println(o);
}
System.out.println("=================");
//两种都遍历
for (Map.Entry<String,String> en :map.entrySet()){
System.out.println(en);
} }
//关于Ancient 的函数,没有get 和 set
public class Ancient {
private String name;
private int age;
public Ancient(String name, int age) {
this.name = name;
this.age = age;
}
public class hashMap {
public static void main(String[] args) {
HashMap<Ancient,String> map = new HashMap<>();
Ancient a1 = new Ancient("杜甫",19);
Ancient a2 = new Ancient("黄景仁",23);
Ancient a3 = new Ancient("王勃",22);
map.put(a1,"一览众山小");
map.put(a2,"别后相思空一水");
map.put(a3,"不坠青云之志");
//重写equals 和 hashCode 方法后 就加不进来了
map.put( new Ancient("杜甫",19),"万里悲秋常作客");
System.out.println(map);
System.out.println("============");
//遍历
for(Ancient anc:map.keySet()){
System.out.println(anc);
}
System.out.println("============");
//全部遍历
for (Map.Entry<Ancient,String> anci :map.entrySet()){
System.out.println(anci);
}
}}
HashCode 源码的总结
- hashMap刚创建时,table是null, 为了节省空间,当添加第一个元素时,table 容量调整为16
- 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的时减少调整元素的个数。
- jdk1.8 当每个链表长度大于8,并且数组个数大于等于 64时,会调整为红黑树,目的是提高执行效率
- jdk1.8 当链表长度小于6,自动调整为链表
- jdk 1.8之前为链表头插入(多线程下会产生死链),后为尾插入
TreeMap的使用
红黑树结构
hsahMap是哈希表
开头来个匿名内部类。就不用在另一个Ancient函数里,实现Comparable接口了
public static void main(String[] args) {
TreeMap<Ancient,String> treeMap = new TreeMap<>(new Comparator<Ancient>() {
@Override
public int compare(Ancient o1, Ancient o2) {
int n1 = o1.getName().compareTo(o2.getName());
int n2 = o1.getAge() - o2.getAge();
return n1==0?n2:n1 ; }
}
);
Ancient a1 = new Ancient("杜甫",19);
Ancient a2 = new Ancient("黄景仁",23);
Ancient a3 = new Ancient("王勃",22);
treeMap.put(a1,"万里悲秋常作客");
treeMap.put(a2,"是此星辰非昨夜");
treeMap.put(a3,"欲穷千里目");
//会运行失败,需要重写comparableTo 方法
先要弄一个接口,public class Ancient implements Comparable <Ancient>
//可以这样写,也可以在开头写,比较省事
System.out.println(treeMap);
//便利操作
for(Ancient a:treeMap.keySet()) {
System.out.println(a);
}
System.out.println(" =============");
for(Map.Entry<Ancient,String> b:treeMap.entrySet()){
System.out.println(b);
}
}
Collections工具类的使用
- sort排序
- binarySearch查找
- Copy复制
- reverse和shuffle
- list集合转为数组
- 数组转为集合,用到Arrays.asList 和 list.toArray()函数
- int数组 类型转换时要用Integer类型不能是int[]
public class someCollection {
public static void main(String[] args) {
List<Integer> list = new ArrayList();
list.add(82);
list.add(23);
list.add(64);
list.add(45);
sort排序之前
System.out.println(list);
//排序之后
Collections.sort(list);
System.out.println(list);
System.out.println("===============");
//binarySearch
int i = Collections.binarySearch(list,45);
System.out.println("位置"+i);
System.out.println("==========");
//Copy复制
List li = new ArrayList();
//新建立的集合必须长度相等才能被复制
for (int k=0;k<list.size();k++){
li.add(0); }
Collections.copy(li,list);
System.out.println(li);
//反转
Collections.reverse(list);
//打乱
Collections.shuffle(list);
//list集合转为数组
System.out.println("====转为数组======");
//类型必须一样,不能是Objict,在开头添加泛型类
Integer[] arr = list.toArray(new Integer[0]);
//这个是错误的打印
System.out.println(arr.toString());
System.out.println(Arrays.toString(arr));
System.out.println("===增强for=====");
for(int o:arr){
System.out.println(o);
}
//数组转为集合,用到Arrays.asList 和 list.toArray()函数
//数组是个受限集合,不能添加或者删除
System.out.println("----数组转为集合-----");
String[] s = {"李白","杜甫","王维","白居易"};
List<String> list2 = Arrays.asList(s);
System.out.println(list2);
//int数组 类型转换时要用Integer类型不能是int[]
Integer[] integes = {199,299,388,23};
List<Integer> list3 = Arrays.asList(integes);
System.out.println(list3);
}
//反转
Collections.reverse(list);
//打乱
Collections.shuffle(list);
//list集合转为数组
System.out.println("====转为数组======");
//类型必须一样,不能是Objict,在开头添加泛型类
Integer[] arr = list.toArray(new Integer[0]);
//这个是错误的打印
System.out.println(arr.toString());
System.out.println(Arrays.toString(arr));
System.out.println("===增强for=====");
for(int o:arr){
System.out.println(o);
}
//数组转为集合,用到Arrays.asList 和 list.toArray()函数
//数组是个受限集合,不能添加或者删除
System.out.println("----数组转为集合-----");
String[] s = {"李白","杜甫","王维","白居易"};
List<String> list2 = Arrays.asList(s);
System.out.println(list2);
//int数组 类型转换时要用Integer类型不能是int[]
Integer[] integes = {199,299,388,23};
List<Integer> list3 = Arrays.asList(integes);
System.out.println(list3);
}