Java类集
指的是一套动态数组的实现方案,但传统数组实现起来十分繁琐,而且长度是致命伤,刚开始依托于链表,与树的数据结构,但数据结构的代码实现困难,数据结构的维护也是十分困难的,性能也难以得到保证,
类集主要的功能:对常见的数据结构实现包装,提供了一系列的接口与实现子类,减少开发困难。
开发时刚开始使用object到现在的泛型,性能不断提升,
Java中的核心接口:
collection,list,set,map,iterator,enumeration,listiterator。
collection接口
java.util.collection是单值集合操作的最大的父接口,在该接口之中定义有所有的单值数据的处理操作。
查看Javajdk api,java.util.collection
核心操作方法:
红色为最常用的方法
list接口
是collection的子接口,元素允许重复,list接口对collection接口进行了扩充,具体方法,查看jdk-api
list本身属于一个接口,那么想要使用则一定要使用子类来完成,list子接口中有三个子类:(90%)arraylist,(8%)vetor,(2%)linkedlist,
arraylist子类
Java中arraylist是实现的list接口,其方法与list相似,
package demo;
import java.util.ArrayList;
import java.util.List;
public class mythread {
public static void main(String[] args) throws InterruptedException {
List<String> arr=new ArrayList<String>();
arr.add("hello");
arr.add("world");
arr.forEach((str)->{
System.out.println(str);
});
}}
在正常开发中并不常用。
观察list集合中其他的操作方法:
package demo;
import java.util.ArrayList;
import java.util.List;
public class mythread {
public static void main(String[] args) throws InterruptedException {
List<String> arr=new ArrayList<String>();
System.out.println("集合是否为空:"+arr.isEmpty()+",集合长度"+arr.size());
arr.add("hello");
arr.add("hello");
arr.add("world");
arr.add("nihao");
System.out.println("集合是否为空:"+arr.isEmpty()+",集合长度"+arr.size());
arr.remove("world");
arr.forEach((str)->{
System.out.println(str);
});
}}
arraylist封装的应该是一个数组,源码啥的不强求,有能力就看。
arraylist实例化时没有传递初始化长度,当数组容量不足时,会采用成倍的方式进行长度增长(10,20,40,80—),使用arraylist时尽量估算出,数据量,如果超过了10个,尽量使用有参构造函数,以避免无用数组空间的产生。
实现自定义类对象的保存
package demo;
import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.List;
class person{
private String name;
private int age;
public person(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
return "姓名:"+this.name+"年龄:"+this.age;
}
}
public class mythread {
public static void main(String[] args) throws InterruptedException {
List<person> all=new ArrayList<>();
all.add(new person("张三" ,12));
all.add(new person("李四" ,13));
all.add(new person("王五" ,14));
all.add(new person("赵六" ,15));
all.forEach(
System.out::println
);
}}
在使用list保存自定义对象的时候如果需要使用 contains(),remove()方法时,一定要保证已经成功覆写了equals()方法,ctrl+o 查看可重写的方法,
package demo;
import com.sun.org.apache.xpath.internal.operations.Equals;
import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.List;
class person{
private String name;
private int age;
public person(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
return "姓名:"+this.name+"年龄:"+this.age;
}
@Override
public boolean equals(Object obj) {
if (this==obj){
return true;
}
if (obj==null){
return false;
}
if (!(obj instanceof person)){
return false;
}
person per=(person)obj;
return this.name.equals(per.name) && this.age==per.age;
}
}
public class mythread {
public static void main(String[] args) throws InterruptedException {
List<person> all=new ArrayList<>();
all.add(new person("张三" ,12));
all.add(new person("李四" ,13));
all.add(new person("王五" ,14));
all.add(new person("赵六" ,15));
System.out.println(all.contains(new person("李四",13)));
all.remove(new person("李四",13));
all.forEach(
System.out::println
);
}}
linkedlist子类
linkedlist实现集合操作:
package demo;
import java.util.LinkedList;
import java.util.List;
public class mythread {
public static void main(String[] args) throws InterruptedException {
List<String> arr=new LinkedList<>();
arr.add("hello");
arr.add("hello");
arr.add("world");
arr.add("nihao");
arr.forEach(
System.out::println
);
}}
从代码的功能来看,与arraylist相似,但从源码来看是不同的,linkedlist中并没有像arraylist中那样的初始化长度的方法,linkeslist类中保存数据都是存在node节点中;在增加数据时,长度size也在增加,(idea中可使用ctrl+shift+r查看源码),linkedlist底层是使用链表实现的,
vector子类
实现了list接口
与其他子类的差别是很小的
package demo;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
public class mythread {
public static void main(String[] args) throws InterruptedException {
List<String> arr=new Vector<>();
arr.add("hello");
arr.add("hello");
arr.add("world");
arr.add("nihao");
arr.forEach(
System.out::println
);
}}
通过源代码分析可以发现 vector类之后中的操作方法都是采用synchronized同步处理的,arraylist中没有使用,vector类之中的方法在多线程访问的时候属于线程安全的
但是性能不如arraylist高,
set集合
不允许存在重复元素,实现collection接口,
jdk1.9之前set集合和collection集合的定义毫无差别,但1.9子后,set集合像list集合也扩充了一些static的方法,使用set.of(e,e)时,不允许元素重复,否则会报错,
hashset
package demo;
import java.util.HashSet;
import java.util.Set;
public class mythread {
public static void main(String[] args) throws Exception{
Set<String> all=new HashSet<>();
all.add("hello");
all.add("world");
all.add("nihao");
all.forEach(System.out::println);
}}
hashset保存元素是无序的,不重复的,
treeset子类
与hashset相比,treeset是有序的
treeset允许自定义类实现排序,但是这个类一定要实现comparable接口,因为只有实现了此接口才能实现排序,treeset本质是利用treemap子类实现的集合数据的存储,而treemap(树)就需要根据comparable来确定大小关系,
package demo;
import java.util.Set;
import java.util.TreeSet;
class person implements Comparable<person>{
private String name;
private int age;
public person(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
return "姓名:"+this.name+"年龄:"+this.age;
}
@Override
public int compareTo(person o) {
if(this.age<o.age){
return -1;
}else if (this.age>o.age){
return 1;
}else {
return this.name.compareTo(o.name);
}
}
}
public class mythread {
public static void main(String[] args) throws Exception{
Set<person> all=new TreeSet<person>();
all.add(new person("张三",19));
all.add(new person("李四",19));
all.add(new person("王五",20));
all.add(new person("王五",20));
all.add(new person("小强",78));
}}
在进行自定义类对象进行比较处理的时候一定要将所有属性都进行比较,不然不同元素,属性相同时,也会被认为是重复数据,所以treeset是使用comparable确认重复数据的,treeset操作过程中,要将类中所有元素属性进行比对,这样难度太高了,实际开发中,首选hashset,hashset判断重复的方式不是使用comparable实现的,而是使用。object类中的hashcode();
对象编码:public int hashcode();
对象比较:public boolean equals(object obj);
在进行重复元素判断的时候首先利用hashcode()进行匹配,如果该编码不存在,证明数据不重复,反之重复,该数据不能存在,
可以选取属性实现自定义类的hashcode()和equals()方法,实现数据的不重复,而只有在排序的要求下,才会使用treeset利用comparable方法实现,
iterator迭代输出
Java1.8之后,iterator接口提供了foreach方法,但不常用在实际开发中,
对于集合操作,常用有四种输出方式:iteratordie迭代输出(最常用),Listiterator双向迭代输出,enumeration枚举输出,foreach输出。
jdk1.5之后collection接口多继承了一个iterable父接口,实现了iterator()操作方法,通过该方法获取iterator接口对象,1.5之前是直接继承collection接口的,
操作:获取iterator接口对象,public Iteratoriterator();
java.scanner类是iterator接口的子类,
使用iterator输出
package demo;
import java.util.Iterator;
import java.util.Set;
public class mythread {
public static void main(String[] args) throws Exception{
Set<String> all=Set.of("hello","world","good");
Iterator<String> iterator=all.iterator();
while (iterator.hasNext()){
String net=iterator.next();
System.out.println(net);
}
}}
但是对于iterator中remove()方法没必要不要使用,与collection中的remove()方法相冲突,此外,iterator.remove()方法删除对象时,原对象也会删除该对象,
请解释collection中和iterator中的remove()方法有什么区别,
使用collection中remove方法时会导致并发更新报错,应该是有iterator中的remove方法,
ListIterator接口
双向迭代输出,需要获取LsitIterator接口实现,
package demo;
import java.util.*;
public class mythread {
public static void main(String[] args) throws Exception{
List<String> all=new ArrayList<>();
all.add("hello");
all.add("world");
all.add("good");
ListIterator<String> iterator=all.listIterator();
System.out.println("由前向后输出");
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("有后向前输出");
while (iterator.hasPrevious()){ //判断是否有前一个元素
System.out.println(iterator.previous()); //输出上一个元素
}
}}
Enumeration输出
为vector类提供服务,想要获取enumeration接口对象,必须依靠vector类,
获取enumeration:public Enumeration elements();
操作方法:判断是否有下一个元素:public boolean hasmoreelements();
获取当前元素:public nextElement();
package demo;
import java.util.*;
public class mythread {
public static void main(String[] args) throws Exception{
Vector<String> all=new Vector<>();
all.add("hello");
all.add("world");
all.add("good");
Enumeration enumeration=all.elements();
while (enumeration.hasMoreElements()){
System.out.println(enumeration.nextElement());
}
}}
foreach输出
jdk1.5以后加强型的for循环也能输出集合了
package demo;
import java.util.*;
public class mythread {
public static void main(String[] args) throws Exception{
List<String> all=new ArrayList<>();
all.add("hello");
all.add("world");
all.add("good");
for (String str:all){
System.out.println(str);
}
System.out.println(all);
}}
map接口
在开发中collection集合保存数据是为了输出,map(key,value)集合保存数据是为了查找,
map中的核心操作方法:
向集合中保存数据:public V put(K key,V value);
根据key查找数据:public V get(object key);
将map集合转为set集合:public set<map.entry<key,value>>entryset();
查询是否key存在:public boolean containsKey(object key)
将map集合中的key转为set集合:public set keyset();
删除key对应的数据:public V remove(object key);
观察代码,看map集合的特点:
package demo;
import java.util.HashMap;
import java.util.Map;
public class mythread {
public static void main(String[] args) throws Exception {
Map<String,Integer> map=new HashMap<>();
map.put("xiao",2);
System.out.println(map);
}}
map一般通过子类实现接口,有hashmap,hashtable,treemap,linkedhashmap。
hashmap
其特点是无序,key不重复,
通过hashmap实例化的map接口,即使key重复也不会报错,而是出现内容的替换,key重复时,使用put方法会返回旧数据,key为空时也不会报错,
hashmap的扩充机制,初始为十六个,当存入0.75倍容量时开始扩充,每次扩容都是2倍的容量,hashmap之中进行数据存储是利用node完成的,jdk1.8之后hashmap的实现变成了红黑树实现,是为了应对讲到来的大数据时代,
linkedhashmap
数据是否有序对map无影响,希望map中数据为增加顺序,则可更换子类为linkedhashmap,使用linkedhashmap时数据量尽量不要太大,时间复杂度会很大,
其定义如下:
public class linkedhashmap<K,V> extends hashmap<k,v> implement map<k,v>
hashtable
是动态数组实现类,key和value均不能为空,否则会出现异常,
其定义如下:
pu’blic class hashtable<k,v> entends dictionary<k,v>
implements map<k,v>,cloneable,serializable,
hsahmap,和hsahtable的区别,
hashmap均是异步操作,hashmap允许保存null,线程安全,
hashtable是同步操作,不允许存在key或value为空,线程不安全,
map.entry内部接口
在map集合中,map.entry的主要作用就是作为一个key和value的包装类型使用,大部分情况下,在进行数据存储是会把key和value包装成一个hander节点。
使用iterator输出map集合
map中没有返回iterator对象的方法,为什么不直接使用iterator对象输出map呢,在map中实际存储的还是key和value的单值,
要想使用iterator实现map集合的输出则必须按照以下步骤实行:
利用map接口中提供的entryset()方法将map集合转为set集合,
利用set集合中的iterator()方法将set集合转为iterator接口实例,
利用iterator进行迭代输出每一组的map.entry对象,随后通过getkey与getvalue实现获取数据。
观察代码
package demo;
import com.sun.javafx.collections.MappingChange;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class mythread {
public static void main(String[] args) throws Exception {
Map<String,Integer> all=new HashMap<>();
all.put("one",1);
all.put("two",2);
Set<Map.Entry<String,Integer>> set= all.entrySet();
Iterator<Map.Entry<String,Integer>> iter=set.iterator();
while (iter.hasNext()){
Map.Entry<String,Integer> mt=iter.next();
System.out.println(mt.getKey()+"***"+mt.getValue());
}
}}
在开发中主要使用在数据的查找,也可以使用foreach方法
package demo;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class mythread {
public static void main(String[] args) throws Exception {
Map<String,Integer> all=new HashMap<>();
all.put("one",1);
all.put("two",2);
Set<Map.Entry<String,Integer>> set= all.entrySet();
for(Map.Entry<String,Integer> entry:set){
System.out.println(entry.getKey()+"***"+entry.getValue());
}
}}
自定义map的key类型
使用自定义的类型作为key时,hashcode()和equals() 方法不能正常使用,如果坚持使用时,一定要重写这俩方法,
package demo;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
class person{
private String name;
private int 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 age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public person(String name,int age){
this.name=name;
this.age=age;
}
}
public class mythread {
public static void main(String[] args) throws Exception {
Map<person,String> map=new HashMap<>();
map.put(new person("小强",18),"琳若"); //使用自定义类作为key值
System.out.println(map.get(new person("小强",18)));
}}
尽量使用常用的string,long,integer这三种
提问hash冲突是如何解决的,
1.当出现了hash冲突时,为保证程序正常执行,会在冲突的位置将所有重复的hash冲突的内容转成链表转成,
stack栈操作
一种先进后出的数据结构。
基本定义:public class stack extends vector
基本操作:入栈public E push();
出栈 public E pop();
栈空时,出栈会出现栈空异常,
package demo;
import java.util.Stack;
public class mythread {
public static void main(String[] args) throws Exception {
Stack<String> all=new Stack<>();
all.push("hello");
all.push("world");
while (!all.isEmpty()){
System.out.println(all.pop());
}
}}
queue队列
一种先进先出的数据结构,
如果将队列应用在多线程的生产者与消费者的模型处理上,那么对于生产者生产速度快于消费者,那么就没有必要消费者获取数据了,可以直接将数据放在队列中,
队列的实现可以使用linkedlist子类实现,
队列定义:
操作方法:向队列中追加数据:public boolean offer(E) ,也可以使用add方法,
通过队列获取数据:public E poll(),弹出后删除数据,
观察代码:
package demo;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class mythread {
public static void main(String[] args) throws Exception {
Queue<String> qu=new LinkedList<>();
qu.offer("A");
qu.offer("B");
qu.offer("C");
System.out.println(qu.peek()); //查看队列头元素
System.out.println(qu.poll()); //获取并删除队头元素
System.out.println(qu.poll());
System.out.println(qu.poll());
}}
除了linkedlist实现之外,也可以使用优先级队列(priorityqueue)实现,
根据需求选择使用,
观察代码
package demo;
import java.util.PriorityQueue;
import java.util.Queue;
public class mythread {
public static void main(String[] args) throws Exception {
Queue<String> qu=new PriorityQueue<>();
qu.offer("A");
qu.offer("B");
qu.offer("C");
System.out.println(qu.peek()); //查看队列头元素
System.out.println(qu.poll()); //获取并删除队头元素
System.out.println(qu.poll());
System.out.println(qu.poll());
}}
properties属性操作
*.properties 资源文件,
以key-value形式保存数据,且只能保存字符串,与map相似,区别在于其保存内容只能是字符串,java.util包里面提供有properties类型,此类时hashtable的子类,
主要操作方法:setproperties(),getproperties()
也可以使用输入流输出流输出属性,
查看代码:
package demo;
import java.util.Properties;
public class mythread {
public static void main(String[] args) throws Exception {
Properties prop=new Properties();
prop.setProperty("good","good1");
prop.setProperty("java","good2");
System.out.println(prop.getProperty("good"));
System.out.println(prop.getProperty("java"));
prop.store(new FileOutputStream(new File("D:"+File.separator+"info.properties")),"中文时看不见得,English才能看见"); //写入内容
}}
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;
public class mythread {
public static void main(String[] args) throws Exception {
Properties prop=new Properties();
prop.load(new FileInputStream(new File("D:"+File.separator+"info.properties"))); //读取资源文件
System.out.println(prop.getProperty("good"));
}}
一般用来处理资源文件,配置信息,十分好用,
collections工具类
一组集合数据的操作工具类,
观察代码
package demo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class mythread {
public static void main(String[] args) throws Exception {
List<String> aa=new ArrayList<>();
Collections.addAll(aa,"hello","good","world");
System.out.println(aa);
Collections.reverse(aa);
System.out.println(aa);
System.out.println(Collections.binarySearch(aa,"hello")); //二分查找hello,返回索引下标,
}}
good good stay,
客官,七百行能换您一个赞吗!!!!