手写简单HashMap和比较器以及Lambda重要知识点

HashMap

  • 1.存储键值对的数据 key value->在哈希表结构中
  • 2.key获取hashcode()值一个int和整数,根据hash算法进行计算,算出桶的位置
  • hash算法: hashcode()值 % 数组的长度
  • hashcode()值 & 数组的长度-1 ---->数组的长度必须为2的整数幂
  • 3.先判断对应桶中是否已经存在数据,判断桶中的数据是否与我当前的key相等,使用equals(),如果相等value覆盖,如果不相等,把数据放入链表的最后
  • 对应桶中是否已经存在数据那就直接放入桶中
  • 如果equals相等,hashcode一定要保证相等,保证相等的数据桶的位置一样,才会比较equals进行去重
  • hashcode相等,equals不一定相等,所以我才要放入桶的时候比较equals()
  • 总结: 如果使用hashMap存储数据,key是自定义的引用的数据类型,一定要重写hashcode()和equals()方法
  • java8:哈希表(数组+链表+红黑树):当桶中的数据超过8个,把结构当前链表结构变为红黑树
  • 初始容量:16
  • 加载因子:0.75 当16*0.75达到临界点12进行扩容
  • 扩容: 扩容位桶的大小
  • 如何处理HashMap线程安全问题:
    •   	1.可以使用Hashtable
      
    •   	2.在Collections的提高了一个方法synchronizedMap(Map<K,V> m) 返回一个线程安全的map
      
    •   	3.juc包(高级并发编程包)下ConcurrentHashMap,是一个线程安全的HashMap--推荐,效率高
      

字符串中如果内容相等,hashcode肯定相同,因为String对hashcode方法进行重写

String s1=new String("哈哈");
String s2=new String("哈哈");
System.out.println(s1.hashCode() == s2.hashCode());

手写简单HashMap

/**
 * 自定义简单实现HashMap
 * @author zhuch
 *
 */
public class MyHashMap {
	Node[] table;//数组
	int size;//存储数组的个数
	//构造器
	public MyHashMap() {
		table=new Node[16];//默认初始容量为16		length为2的整数幂
	}
	
	
	//添加put
	public void put(Object key,Object value) {
		int hash=myHash(key.hashCode(),table.length);
		Node newNode=new Node();//存储当前键值对的节点
		newNode.hash=hash;
		newNode.key=key;
		newNode.value=value;
		newNode.next=null;
		
		Node node=table[hash];//hash是刚刚根据key计算出来的桶的位置|素组的索引
		//现在桶中没有节点数据,当前节点newNode就作为第一个
		if(node==null) {
			table[hash]=newNode;
			size++;
		}else {
			//拿到链表头节点 如果node不等于Null,就作为链表头节点存在
			while(true) {
				//如果当前key与桶中的已有节点key相等,value覆盖
				if(node.key.equals(key)) {
					node.value=value;
					break;
				}
				//判断当前是否为最后一个节点
				if(node.next==null) {
					node.next=newNode;
					size++;
					break;
				}
				//如果没有覆盖,继续从我这个节点找到下一个节点
				node=node.next;//node用于当前比较桶中的数据节点
			}
		}
		
	}
	
	public int myHash(int Keycode,int length) {
		return Keycode & length-1;
	}
	
	public static void main(String[] args) {
		MyHashMap my=new MyHashMap();
		System.out.println(my.size);
		my.put(1, "a");
		my.put(2, "b");
		my.put(3, "c");
		System.out.println(my.size);
		my.put(3, "d");
		System.out.println(my.size);
	}
	
}
class Node{
	int hash;//桶的位置,也就是Node数组的索引值
	Object key;
	Object value;
	Node next;// Node next=new Node();
}

Collections

操作容器的工具类

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TestCollections {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Integer> list=new ArrayList<Integer>();
		list.add(14);
		list.add(30);
		list.add(22);
		list.add(8);
		System.out.println("--------------随机--------------");
		//随机
		Collections.shuffle(list);
		System.out.println(list);
		
		System.out.println("--------------排序--------------");
		//排序
		Collections.sort(list);
		System.out.println(list);
		
		System.out.println("--------------交换位置--------------");
		//交换位置,通过索引
		Collections.swap(list, 0, 1);
		System.out.println(list);
		
	}

}

比较器

确定两个对象之间的大小关系及排列顺序称为比较,能实现这个比较功能的类或方法称之为比较器,在java中只有两种比较器。

比较器的分类

内部比较器(Comparable接口)和外部比较器(Comparator接口)

内部比较器

把比较器写在类的内部

​ 类实现了Comparable接口,然后重写了compareTo方法(这个方法可以看作比较器),这个类就拥有了内部比较器。注意,你一旦实现了比较器,就说明这个类支持排序。

/**
 * 内部比较器
 */
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollecitonsTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Teacher> list=new ArrayList();
		Teacher t1=new Teacher(150,"小红");
		Teacher t2=new Teacher(160,"小白");
		list.add(t1);
		list.add(t2);
//		Arrays.sort(t);
//		System.out.println(A);
		Collections.sort(list);
		System.out.println(list);
	}

}

class Teacher implements Comparable<Teacher>{
	
	private int height;
	private String name;
	
	
	public Teacher() {
		super();
	}

	
	
	public Teacher(int height, String name) {
		super();
		this.height = height;
		this.name = name;
	}



	public int getHeight() {
		return height;
	}
	

	public void setHeight(int height) {
		this.height = height;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Teacher [height=" + height + ", name=" + name + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + height;
		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;
		Teacher other = (Teacher) obj;
		if (height != other.height)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}





	@Override
	public int compareTo(Teacher o) {
		// TODO Auto-generated method stub
	
		return o.height-this.height;
	}

	
	
}
外部比较器

把比较器写在类的外部

​ 新定义一个类,类名自定,但这个类必须实现Comparator接口,重写compare方法,我们把这个称作外部比较器。

/**
 * 外部比较器
 */
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CollectionsTest02 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Teacher> list=new ArrayList();
		Teacher t1=new Teacher(150,"小红");
		Teacher t2=new Teacher(160,"小白");
		list.add(t1);
		list.add(t2);
		
		Collections.sort(list, new CompareTest());
		System.out.println(list);
	}

}
class CompareTest implements Comparator<Teacher>{

	@Override
	public int compare(Teacher o1, Teacher o2) {
		// TODO Auto-generated method stub
		return o2.compareTo(o1);
	}
	
}

Lambda

  • 简化匿名内部类:
  • java8提供了lambda表达式
  • 使用前提:函数式接口
  • 函数式接口: 只有一个必须要重写的抽象方法的接口
  • 检查函数式接口:@FunctionalInterface
  • 语法:
  •  ()->{}
    
  •  () :要重写的抽象方法的参数列表
    
  •  -> :lambda符号,箭头符号,箭头函数,具有上下文推到作用
    
  •  {} :定义抽象方法的方法体
    
//字符串大写转小写,字符串截取
public class TestLambda02 {
	
	public static void main(String[] args) {
		String str="abcdefg";
//		System.out.println(str.toUpperCase());
		
		//Lambda 小写转大写
		StringTest st=str1->str1.toUpperCase();
		str=st.getValue(str);
		System.out.println(str);
		//Lambda 字符串截取
		StringTest st1=str2->str2.substring(2, 5);
		str=st1.getValue(str);
		System.out.println(str);
		
		
	}
}

interface StringTest{
	public String getValue(String str);
}
发布了13 篇原创文章 · 获赞 13 · 访问量 504

猜你喜欢

转载自blog.csdn.net/Rabbit_white_/article/details/103996844
今日推荐