欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Hashtable、Map.Entry、自定义key、Stack、Properties、Collections

程序员文章站 2022-06-02 23:25:49
...

目录

Hashtable

Hashtable、Map.Entry、自定义key、Stack、Properties、Collections
Hashtable的key和value都不允许为null,为null会报NullPointerException。

示例:

public class TestHashtable {
    public static void main(String[] args) {
        Map<String,String> map = new Hashtable<>();
        map.put("1","one");
        map.put("2","two");
        map.put("3","three");
        map.put("null",null);
        map.put("4","four");
        System.out.println(map);
    }
}

结果:

Exception in thread "main" java.lang.NullPointerException
	at java.base/java.util.Hashtable.put(Hashtable.java:475)
	at com.tx.map.TestHashtable.main(TestHashtable.java:17)

hashtable扩容:

int newCapacity = (oldCapacity << 1) + 1;	//hashtable扩容

Hashtable和HashMap的区别:

​ 1、Hashtable的key和value不运行为null,HashMap的key和value可以为null。

​ 2、HashMap的初始容量为0,第一次使用put()是容量增加为16,Hashtable无参构造容量默认为11。

​ 3、HashMap和hashtable的阈值都为75%,超过自动增加,但HashMap每次扩容翻1倍(oldCap << 1),Hashtable扩容翻1倍加1((oldCap << 1) + 1)。

​ 4、HashMap在存入8个数据之后转为红黑树,Hashtable不会转变为红黑树。

​ 5、HashMap使用线程异步处理,属于非线程安全,Hashtable使用synchronized进行线程同步处理,属于线程安全。

Map.Entry

Map.Entry是Map的一个内部接口,可以使用getKey()和getValue()来获取key的值和value的值。

Hashtable、Map.Entry、自定义key、Stack、Properties、Collections

示例:

public class TestMapEntry {
    public static void main(String[] args) throws IOException {
        Map<String, String> map = new HashMap<>(20);
        map.put("1", "one");
        map.put("2", "two");
        map.put("3", "three");
        map.put("4", "four");
        map.put("5", "five");

        System.out.println(map.get("5"));
        System.out.println();

        System.out.println(map);
        System.out.println();

        long time = getKeyForeach(map);
        System.out.println("耗时 ->"+time);
        System.out.println();
		//Map使用entrySet转换为Set调用iterator使用Iterator进行输出
        Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
       	long data = getKey(iterator);
        System.out.println("耗时 ->"+data);
    }

    /**
     * 迭代输出Map.Entry内存储的值
     * 数据多时,用while
     * @param iterator  Iterator实例
     */
    private static long getKey(Iterator<Map.Entry<String, String>> iterator) {
        long timeA = System.currentTimeMillis();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            System.out.println("key() ->" + entry.getKey() + "、Value() ->" + entry.getValue());
        }
        long timeB = System.currentTimeMillis();
        return timeB - timeA;
    }

    /**
     * foreach循环输出Map.Entry内存储的值
     * 耗时比while多20倍
     * @param map map的实例
     */
    private static long getKeyForeach(Map<String, String> map) {
        long timeA = System.currentTimeMillis();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println("key ->" + entry.getKey() + "、value ->" + entry.getValue());
        }
        long timeB = System.currentTimeMillis();
        return timeB - timeA;
    }
}

结果:

five

{1=one, 2=two, 3=three, 4=four, 5=five}

key ->1、value ->one
key ->2、value ->two
key ->3、value ->three
key ->4、value ->four
key ->5、value ->five
耗时 ->23

key() ->1Value() ->one
key() ->2Value() ->two
key() ->3Value() ->three
key() ->4Value() ->four
key() ->5Value() ->five
耗时 ->0

自定义Key

1、使用对象做key时,需要重写HashCode()和equals()获取哈希码,来进行对象比较。

2、因为哈希码是数字,使用哈希码进行比较时,比较的速度更快。

3、发现哈希码相同才会进行内容的比较。

在未重写的情况下:

public class TestTargetKey {
    public static void main(String[] args) {
        Map<Ball,String> map = new HashMap<>(16);
        map.put(new Ball("篮球",155.5),"1");
        System.out.println(map.get(new Ball("篮球",155.5)));
    }
}
class Ball{
    private String name;
    private double price;

    public Ball(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public String toString() {
        return "Ball{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

结果:

null

在重写的情况下:

public class TestTargetKey {
    public static void main(String[] args) {
        Map<Ball,String> map = new HashMap<>(16);
        map.put(new Ball("篮球",155.5),"1");
        System.out.println(map.get(new Ball("篮球",155.5)));
    }
}
class Ball{
    private String name;
    private double price;

    public Ball(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public String toString() {
        return "Ball{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Ball ball = (Ball) o;
        return Double.compare(ball.price, price) == 0 &&
                Objects.equals(name, ball.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, price);
    }
}

结果:

1

当哈希码相同(哈希冲突)时,解决方法有四个(开放定址法、链地址法、再哈希法、建立公共的溢出区),Java使用链地址法,将相同哈希码的数据,使用链表的形式进行存储,查找时,再使用内容的比较。

Hashtable、Map.Entry、自定义key、Stack、Properties、Collections

Stack

Stack是Vector的子类,Stack栈的操作先入后出。

入栈:

Hashtable、Map.Entry、自定义key、Stack、Properties、Collections
出栈:

Hashtable、Map.Entry、自定义key、Stack、Properties、Collections
常用方法:

方法 说明
public E push(E item) 向栈中增加数据
public synchronized E pop() 弹出数据(先进后出)
public boolean empty() 判断栈中是否存在数据

示例:

public class TestStack {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        stack.push("1");
        stack.push("2");
        stack.push("3");
        stack.push("4");
        stack.push("5");
        stack.push("6");
        stack.push("7");
        stack.push("8");
        while(!stack.empty()){	//空栈判断,当栈为空仍进行pop输出时,会报出EmptyStackException
            System.out.print(stack.pop()+"、");
        }
    }
}

结果:

87654321

当栈中数据为空使用pop时:

Exception in thread "main" java.util.EmptyStackException

Properties

常用方法:

方法 说明
public Properties() { this((Properties)null, 8); } Properties的无参构造,默认的容量为8
public synchronized Object setProperty(String key, String value) 设置属性的key和value值
public String getProperty(String key) 获取属性,key不存在输出null
public String getProperty(String key, String defaultValue) 获取属性,不存在key则输出defaultValue
public void list(PrintStream out) 列出全部属性
public void list(PrintWriter out) 列出全部属性
public void store(Writer writer, String comments) throws IOException 向字符输出流输出全部属性
public void store(OutputStream out, String comments) throws IOException 向字节输出流输出全部属性
public synchronized void load(InputStream inStream) throws IOException 从字节输入流读取数据
public synchronized void load(Reader reader) throws IOException 从字符输入流读取数据

示例:

public class TestProperties {
    public static void main(String[] args) throws IOException {
        //PrintWriter的实例
        PrintWriter printWriter = new PrintWriter("D:" + File.separator + "TestFour.properties");
        //PrintStream的实例
        PrintStream printStream = new PrintStream("D:" + File.separator + "TestThree.properties");
        //Properties的实例
        Properties properties = new Properties();
        //setProperty():增加数据
        properties.setProperty("1", "one");
        properties.setProperty("2", "two");
        properties.setProperty("3", "three");
        properties.setProperty("4", "four");
        properties.setProperty("5", "five");
        //输出properties
        System.out.println(properties);
        //getProperties():根据key获取value值
        System.out.println(properties.getProperty("1"));
        //getProperties():根据key获取value值,key不存在返回null
        System.out.println(properties.getProperty("6"));
        //getProperties():根据key获取value值,key不存在返回自定义设置的defaultValue值
        System.out.println(properties.getProperty("6", "value不存在数据"));
        //store():将数据存入指定指定文件内,输入注释内容
        properties.store(new FileOutputStream("D:" + File.separator + "TestOne.properties", true), "Properties输出测试");
        //store():将数据存入指定指定文件内,输入注释内容
        properties.store(new FileWriter("D:" + File.separator + "TestTwo.properties", true), "Properties输出测试");
        //list():在指定的文件处,打印数据
        properties.list(printStream);
        //list():在指定的文件处,打印数据
        properties.list(printWriter);
        //将指定文件的数据输入到properties内
        properties.load(new FileInputStream("D:" + File.separator + "TestOne.properties"));
        //将指定文件的数据输入到properties内
        properties.load(new FileReader("D:" + File.separator + "TestTwo.properties"));
        //在将指定文件输入后,可以利用文件内数据的key获取value值
        System.out.println(properties.getProperty("3"));
        printStream.close();
        printWriter.close();
    }
}

结果:

{1=one, 2=two, 3=three, 4=four, 5=five}
one
null
value不存在数据
three

Hashtable、Map.Entry、自定义key、Stack、Properties、Collections

Collections

​ 用来弥补传统类集的设计不足。

Hashtable、Map.Entry、自定义key、Stack、Properties、Collections

示例:

public class TestCollections {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list,"5","2","1","4","3");
        Collections.sort(list);
        System.out.println(list);
        System.out.println(Collections.binarySearch(list,"3"));
    }
}

结果:

[1, 2, 3, 4, 5]
2
相关标签: 学习总结