一。 二叉树递归泛型版
泛型比较大小转成Comparable调用compareTo
将泛型值t强转Comparabl,调用compareTo用来比较
public class Treetwo2<T> {
public class Node<T> {
private T date;
private Node<T> lift;
private Node<T> right;
private Node(T date) {
this.date = date;
}
}
private Node root;
private void addToNode(Node node,T t){
if(((Comparable)t).compareTo(node.date)<0){//将泛型值t强转Comparabl,调用compareTo用来比较
//date加到左边
if(node.lift==null){//节点左边如果为空把t给左边并return退出
node.lift=new Node<T>(t);
return;
}
addToNode(node.lift,t);//如果节点左边不空,继续调用本身访问左边下个节点
}
else if (((Comparable)t).compareTo(node.date)>0){
//date右移动
if(node.right==null){
node.right=new Node<T>(t);
return;
}
addToNode(node.right,t);
}
}
public void add(T t){
if(root==null){
root=new Node(t);
return;
}else{
addToNode(root,t);
}
}
public void trivelNode(Node<T> node){
if(node.lift!=null){
trivelNode(node.lift);
}
System.out.println(node.date);
if(node.right!=null){
trivelNode(node.right);
}
}
public void trivel(){
trivelNode(root);
}
}
二。 List
List(I): ArrayList:数组 LinkedList:双向链表 Vector
可使用下标
add(index, E e), remove(index)
get(index), set(index, E e)
1.ArrayList和LinkedList效率比较
public class ArryAndLinked {
public static void main(String[] args) {
ArrayList<String> arrayList=new ArrayList<>();
LinkedList<String> linkedList=new LinkedList<>();
for(int i=0;i<1000000;i++){
arrayList.add("1");
linkedList.add("1");
}
//比较从头部访问的速度
long time1=System.currentTimeMillis();
arrayList.get(10);
long time2=System.currentTimeMillis();
System.out.println("头部访问速度"+(time2-time1));
long time3=System.currentTimeMillis();
linkedList.get(10);
long time4=System.currentTimeMillis();
System.out.println("头部访问速度"+(time4-time3));
//比较从中间访问的速度
long time5=System.currentTimeMillis();
arrayList.get(500000);
long time6=System.currentTimeMillis();
System.out.println("中部访问速度"+(time6-time5));
long time7=System.currentTimeMillis();
linkedList.get(500000);
long time8=System.currentTimeMillis();
System.out.println("中部访问速度"+(time8-time7));
//比较从尾部访问的速度
long time9=System.currentTimeMillis();
arrayList.get(980000);
long time10=System.currentTimeMillis();
System.out.println("尾部访问速度"+(time10-time9));
long time11=System.currentTimeMillis();
linkedList.get(980000);//linkedList是双向链表
long time12=System.currentTimeMillis();
System.out.println("尾部访问速度"+(time12-time11));
System.out.println("----------------------");
//比较插入速度
//头部插入速度
long time01=System.currentTimeMillis();
arrayList.add(10,"2");//ArryList每插入一个,后面所有都要向后面移
long time02=System.currentTimeMillis();
System.out.println("头部访问速度"+(time02-time01));
long time03=System.currentTimeMillis();
linkedList.add(10,"2");//链表插入可以在这个位置直接插入,应为其空间位置不是连续的
long time04=System.currentTimeMillis();
System.out.println("头部访问速度"+(time04-time03));
//中部插入
long time05=System.currentTimeMillis();
arrayList.add(500000,"2");//ArryList每插入一个,后面所有都要向后面移,所以插入位置越靠后越快
long time06=System.currentTimeMillis();
System.out.println("头部访问速度"+(time06-time05));
long time07=System.currentTimeMillis();
linkedList.add(500000,"2");
long time08=System.currentTimeMillis();
System.out.println("头部访问速度"+(time08-time07));
//尾巴部插入
long time09=System.currentTimeMillis();
arrayList.add(980000,"2");
long time010=System.currentTimeMillis();
System.out.println("头部访问速度"+(time010-time09));
long time011=System.currentTimeMillis();
linkedList.add(980000,"2");
long time012=System.currentTimeMillis();
System.out.println("头部访问速度"+(time012-time011));
}
}
2.LinkedList独有的方法 - 了解
linkList.addFirst("");
linkList.addLast("");
linkList.removeFirst();
linkList.removeLast();
linkList.getFirst();
linkList.getLast();
三。Set
1. 实现类 HashSet:
HashSet: 散列表/无序的, 不是随机!! 不允许重复元素
add原理: 详见图
remove原理
结论: hashCode和equals要一起重写
注意: equals方法判断相同的两个对象, hashCode方法结果一定要一致
equals判断不相同的两个对象, hashCode结果要尽量不一样
public class Studengt {
private int age;
private String name;
public Studengt(int age,String name){
this.age=age;
this.name=name;
}
@Override
public String toString() {
return age +
", "+name+'\n';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Studengt studengt = (Studengt) o;
return age == studengt.age &&
Objects.equals(name, studengt.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
加上get/set代码
public class HashCode1 {
public static void main(String[] args) {
Set<Studengt>set=new HashSet<>();
set.add(new Studengt(18,"张三"));
set.add(new Studengt(18,"张三"));
set.add(new Studengt(20,"王二"));
set.add(new Studengt(20,"李久"));
System.out.println(set);
System.out.println("----------");
Studengt s1=new Studengt(18,"张三");
Studengt s2=new Studengt(30,"六六");
Studengt s3=new Studengt(18,"离奇");
Set<Studengt>set1=new HashSet<>();
set1.add(s1);
set1.add(s2);
set1.add(s3);
System.out.println(set1);
s1.setAge(22);
set1.remove(s1);//s1的属性改变之后其哈希码改变导致和之前哈希地址不同,无法找到删除s1
System.out.println(set1);
}
}
①判断元素是否相同,是否要add进去:
Student没有重写equals和hashCode, 全部new出来的哈希码不同
重写了equals方法, 但是没有重写hashCode, 全部new出来的哈希码不同
重写了hashCode方法, 但是没有重写equals, new出的元素数组地址相同,但无法比较数组地址下的链表内容
重写了equals和hashCode方法, 能找到数组地址并比较数组地址下的链表内容,相同的就不添加
② 元素属性值发生了改变,用remove移除,移除的时候,重新计算位置,发现位置上找不到s1对象,不会移除。
③ Object中 hashCode() 方法默认得到的是 对象的物理地址
hashCode没有重写, 所有对象的哈希值都不一样
但哈希值不一样, 定位到的set中的位置, 可能相同
2 . SortedSet(I)接口
|- 实现类TreeSet: Comparable Comparator
特点: 不允许重复, 和equals方法无关
取决于 compare 或者 compareTo 方法
public class TreeSet1 {
public static void main(String[] args) {
// 可以通过构造方法, 传入比较器
Set<String>set=new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {//相同就不会输出
return o1.length()-o2.length();
}
});
set.add("aaa");
set.add("bbbb");
set.add("gg");
set.add("oooop");
System.out.println(set);
System.out.println("_____________");
Set<Studengt>set1=new TreeSet<>(new Comparator<Studengt>() {
@Override
public int compare(Studengt o1, Studengt o2) {
return o1.getAge()-o2.getAge();
}
});
set1.add(new Studengt(18,"李四"));
set1.add(new Studengt(18,"王五"));
set1.add(new Studengt(20,"李四"));
System.out.println(set1);
System.out.println("______________");
Set<Integer>set2=new TreeSet<>();//没重写Compalable也会用默认方法排序
set2.add(1);
set2.add(2);
set2.add(3);
set2.add(3);
set2.add(7);
set2.add(5);
System.out.println(set2);
}
}
四。Map
Map(I): 映射表 key->value, 通过key 获得value
Map中的key, 单独的一部分, 就是Set
|- HashMap
|- TreeMap
1.HashMap
常用API:
V put(key, value)
V remove(key)
V get(key)
containsKey containsValue isEmpty size…
putAll
public class Map1 {
public static void main(String[] args) {
Map<Integer,String>map=new HashMap<>();
//1添加.put的返回值:对应key之前的value内容
map.put(1,"黑土");
map.put(4,"黑龙江");
map.put(3,"铁岭");
map.put(2,"白云");
//会自动用默认的hashcode排序
System.out.println(map);
//2移除。remove返回值:被移除前的value
map.remove(1);
String m=map.remove(3);
System.out.println("remove返回值"+m);
System.out.println(map);
//3修改集合中的元素
String s=map.put(2,"乌云");
map.put(5,"老树");
System.out.println("put返回值"+s);//put的返回值:对应key之前的value内容
System.out.println(map);
//4获得get 返回值value
System.out.println(map.get(2));
}
}
2.迭代Map对应的三个方法
entrySet()
keySet()
values()
public class MapTrivel {
public static void main(String[] args) {
Map<String,String>map=new HashMap<>();
map.put("黑土","11236");
map.put("白云","7764");
map.put("简自豪","7764");
map.put("郭德纲","7764");
//①获取所有的键,成键集
Set<String>keys=map.keySet();
//遍历键集
for(String ke:keys){
//ke为键。然后获取对应value
String value=map.get(ke);
System.out.println(ke+"="+value);
}
System.out.println("------------");
//②获取所有entry对象。键值对
Set<Entry<String,String>> entrySet=map.entrySet();//如果没导包Entry写成Map.Entry
//遍历得到的每一个entry对象
for(Entry<String,String>entry:entrySet){
//将键值对分解
String key=entry.getKey();//获取key
String value=entry.getValue();//获取value
System.out.println(key+"="+value);
}
System.out.println("-------------");
//③只能遍历value
Collection<String>value=map.values();
for(String va:value){
System.out.println(va);
}
}
}
3.判断字符串中各字符出现的个数
public class Exice {//判断字符出现的次数
public static void main(String[] args) {
Scanner consol=new Scanner(System.in);
String str=consol.next();
//将字符转为字符数组
char[] arr=str.toCharArray();
Map<Character,Integer>map=new HashMap<>();
//遍历数组进行统计
for(Character c:arr){
//判断是否首次出现
Integer ori=map.get(c);
if(ori==null){
ori=0;
}
map.put(c,ori+1);
}
System.out.println(map);
}
五。队列Queue
Queue(I): - 队列(offer/poll/peek)
|- Deque(I) - 双端队列(offerFirst/offerLast…)
- 栈(push/pop)
|- LinkedList
1。单向队列Queue
public class Demo01Queue {
public static void main(String[] args) {
// 1.创建队列 - 先进先出
Queue<String> qu = new LinkedList<>();
// 2.进队列的方法
qu.offer("哈哈哈");
qu.offer("嘻嘻嘻");
System.out.println(qu);
// 3.获取队列头元素的方法
String s1 = qu.peek(); // -- 只是查看访问
System.out.println("队列头: " + s1);
System.out.println("队列: " + qu);
s1 = qu.poll(); // -- 获取队列头元素,并将元素从队列中移除
System.out.println("队列头2: " + s1);
System.out.println("队列2: " + qu);
}
}
2.双向队列Deque
public class Demo02Deque {
public static void main(String[] args) {
// 1.创建一个双端队列的方法
Deque<String> dq = new LinkedList<>();
// 2.拥有队列相关的所有方法 offer peek poll
dq.offer("哈哈哈");
dq.offer("嘻嘻嘻");
// 3.可以从队列头和尾加元素
dq.offerFirst("hahaha");
dq.offerLast("heihei"); // 等同于offer方法
System.out.println(dq);
// 4.可以从队列头和尾取元素
String s1 = dq.pollFirst(); // 等同于poll
System.out.println("队列头: " + s1);
System.out.println("队列: " + dq);
s1 = dq.pollLast();
System.out.println("队列尾: " + s1);
System.out.println("队列: " + dq);
}
}
public class Demo03Stack {
public static void main(String[] args) {
// Deque当你使用它的 push 和 pop 方法时, 他就变成了栈
// 链表栈
Deque<String> stack = new LinkedList<>();
stack.push("a");
stack.push("b");
stack.push("c");
System.out.println(stack);
String s = stack.pop();
System.out.println("栈顶元素: " + s);
System.out.println("栈: " + stack);
// 栈: 数组栈
Stack<String> stack2 = new Stack<>();
stack2.push("h");
stack2.push("i");
System.out.println(stack2);
String s2 = stack2.pop();
System.out.println("stack2的栈顶: " + s2);
}
}