package com.bjsxt.others.que; import java.util.ArrayDeque; import java.util.Queue; /** * 使用队列模拟银行存款业务 * @author Administrator * */ public class Demo01 { /** * @param args */ public static void main(String[] args) { Queue<Request> que =new ArrayDeque<Request>(); //模拟排队情况 for(int i=0;i<10;i++){ final int num =i; que.offer(new Request(){ @Override public void deposit() { System.out.println("第"+num+"个人,办理存款业务,存款额度为:"+(Math.random()*10000)); } }); } dealWith(que); } //处理业务 public static void dealWith(Queue<Request> que){ Request req =null; while(null!=(req=que.poll())){ req.deposit(); } } } interface Request{ //存款 void deposit(); }
堆栈相关:
package com.bjsxt.others.que; import java.util.ArrayDeque; import java.util.Deque; /** * 使用队列实现自定义堆栈 * 1、弹 * 2、压 * 3、获取头 * @author Administrator * * @param <E> */ public class MyStack<E> { //容器 private Deque<E> container =new ArrayDeque<E>(); //容量 private int cap; public MyStack(int cap) { super(); this.cap = cap; } //压栈 public boolean push(E e){ if(container.size()+1>cap){ return false; } return container.offerLast(e); } //弹栈 public E pop(){ return container.pollLast(); } //获取 public E peek(){ return container.peekLast(); } public int size(){ return this.container.size(); } }
Demo:
package com.bjsxt.others.que; //测试自定义堆栈 public class Demo02 { /** * @param args */ public static void main(String[] args) { MyStack<String> backHistory =new MyStack<String>(3); backHistory.push("www.baidu.com"); backHistory.push("www.google.com"); backHistory.push("www.sina.com"); backHistory.push("www.bjsxt.cn"); System.out.println("大小:"+backHistory.size()); //遍历 String item=null; while(null!=(item=backHistory.pop())){ System.out.println(item); } } }
Enumeration:
package com.bjsxt.others.en; import java.util.Enumeration; import java.util.Vector; /** * Enumeration 的使用 * 1、判断 hasMoreElements() * 2、获取 nextElement() * * Vector 的 elements()方法 * * * @author Administrator * */ public class Demo01 { /** * @param args */ public static void main(String[] args) { Vector<String> vector =new Vector<String>(); vector.add("javase"); vector.add("html"); vector.add("oracle"); //遍历该Vector Enumeration<String> en =vector.elements(); while(en.hasMoreElements()){ System.out.println(en.nextElement()); } } }
package com.bjsxt.others.en; import java.util.StringTokenizer; /** * Enumeration 子类 * StringTokenizer:String split() 字符串分割 * 不支持正则表达式 * * StringTokenizer(String str, String delim) * @author Administrator * */ public class Demo02 { /** * @param args */ public static void main(String[] args) { String emailStr="[email protected];[email protected];[email protected]"; StringTokenizer token =new StringTokenizer(emailStr,";"); //遍历获取 while(token.hasMoreElements()){ System.out.println(token.nextElement()); } } }
HashMap与Hashtable的区别:
HashTable的应用非常广泛,HashMap是新框架中用来代替HashTable的类,也就是说建议使用HashMap,不要使用HashTable。可能你觉得HashTable很好用,为什么不用呢?这里简单分析他们的区别。
1.HashTable的方法是同步的,HashMap未经同步,所以在多线程场合要手动同步HashMap这个区别就像Vector和ArrayList一样。
2.HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)。
3.HashTable有一个contains(Object value),功能和containsValue(Object value)功能一样。
4.HashTable使用Enumeration,HashMap使用Iterator。
以上只是表面的不同,它们的实现也有很大的不同。
5.HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
6.哈希值的使用不同,HashTable直接使用对象的hashCode,代码是这样的:
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList、Vector和LinkedList。List用于存放多个元素,能够维护元素的次序,并且允许元素的重复。3个具体实现类的相关区别如下:
查看Java源代码,发现当数组的大小不够的时候,需要重新建立数组,然后将元素拷贝到新的数组内,ArrayList和Vector的扩展数组的大小不同。
public boolean add(E e) { ensureCapacity(size + 1); // 增加元素,判断是否能够容纳。不能的话就要新建数组 elementData[size++] = e; return true; } public void ensureCapacity(int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { Object oldData[] = elementData; // 此行没看出来用处,不知道开发者出于什么考虑 int newCapacity = (oldCapacity * 3)/2 + 1; // 增加新的数组的大小 if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } }
private void ensureCapacityHelper(int minCapacity) { int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { Object[] oldData = elementData; int newCapacity = (capacityIncrement > 0) ? (oldCapacity + capacityIncrement) : (oldCapacity * 2); if (newCapacity < minCapacity) { newCapacity = minCapacity; } elementData = Arrays.copyOf(elementData, newCapacity); } }
Property:
package com.bjsxt.others.pro; import java.util.Properties; /** * Properties 资源配置文件的读写 * 1、key 与value 只能为字符串 * 2、存储与读取 * setProperty(String key, String value) * getProperty(String key, String defaultValue) * @author Administrator * */ public class Demo01 { /** * @param args */ public static void main(String[] args) { //创建对象 Properties pro =new Properties(); //存储 pro.setProperty("driver", "oracle.jdbc.driver.OracleDriver"); //pro.setProperty("url", "jdbc:oracle:thin:@localhost:1521:orcl"); pro.setProperty("user", "scott"); pro.setProperty("pwd", "tiger"); //获取 String url =pro.getProperty("url","test"); System.out.println(url); } }
package com.bjsxt.others.pro; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; /** * 使用Properties 输出到文件 * 资源配置文件: * * 1、.properties * store(OutputStream out, String comments) store(Writer writer, String comments) 2、.xml storeToXML(OutputStream os, String comment) :UTF-8字符集 storeToXML(OutputStream os, String comment, String encoding) * @author Administrator * */ public class Demo02 { /** * @param args * @throws IOException * @throws FileNotFoundException */ public static void main(String[] args) throws FileNotFoundException, IOException { //创建对象 Properties pro =new Properties(); //存储 pro.setProperty("driver", "oracle.jdbc.driver.OracleDriver"); pro.setProperty("url", "jdbc:oracle:thin:@localhost:1521:orcl"); pro.setProperty("user", "scott"); pro.setProperty("pwd", "tiger"); //存储到e:/others 绝对路径 盘符: //pro.store(new FileOutputStream(new File("e:/others/db.properties")), "db配置"); //pro.storeToXML(new FileOutputStream(new File("e:/others/db.xml")), "db配置"); //使用相对路径 当前的工程 // pro.store(new FileOutputStream(new File("db.properties")), "db配置"); // pro.store(new FileOutputStream(new File("src/db.properties")), "db配置"); pro.store(new FileOutputStream(new File("src/com/bjsxt/others/pro/db.properties")), "db配置"); } }
package com.bjsxt.others.pro; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.Properties; /** * 使用Properties读取配置文件 * 资源配置文件: * 使用相对与绝对路径读取 * load(InputStream inStream) load(Reader reader) loadFromXML(InputStream in) * @author Administrator * */ public class Demo03 { /** * @param args * @throws IOException * @throws FileNotFoundException */ public static void main(String[] args) throws FileNotFoundException, IOException { Properties pro=new Properties(); //读取 绝对路径 //pro.load(new FileReader("e:/others/db.properties")); //读取 相对路径 pro.load(new FileReader("src/com/bjsxt/others/pro/db.properties")); System.out.println(pro.getProperty("user", "bjsxt")); } }
package com.bjsxt.others.pro; import java.io.IOException; import java.util.Properties; /** * 使用类相对路径读取配置文件 * bin * @author Administrator * */ public class Demo04 { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { Properties pro =new Properties(); //类相对路径的 / bin //pro.load(Demo04.class.getResourceAsStream("/com/bjsxt/others/pro/db.properties")); //"" bin pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("com/bjsxt/others/pro/db.properties")); System.out.println(pro.getProperty("user", "bjsxt")); } }
java 引用分类(摘抄)
在 jdk 1.2 及其以后,引入了强引用、软引用、弱引用、虚引用这四个概念。网上很多关于这四个概念的解释,但大多是概念性的泛泛而谈,今天我结合着代码分析了一下,首先我们先来看定义与大概解释(引用类型在包 java.lang.ref 里)。
1、强引用(StrongReference)
强引用不会被GC回收,并且在java.lang.ref里也没有实际的对应类型。举个例子来说:
Object obj = new Object();
这里的obj引用便是一个强引用,不会被GC回收。
2、软引用(SoftReference)
软引用在JVM报告内存不足的时候才会被GC回收,否则不会回收,正是由于这种特性软引用在caching和pooling中用处广泛。软引用的用法:
Object obj = new Object(); SoftReference<Object> softRef = new SoftReference(obj); // 使用 softRef.get() 获取软引用所引用的对象 Object objg = softRef.get();
3、弱引用(WeakReference)
当GC一但发现了弱引用对象,将会释放WeakReference所引用的对象。弱引用使用方法与软引用类似,但回收策略不同。
4、虚引用(PhantomReference)
当GC一但发现了虚引用对象,将会将PhantomReference对象插入ReferenceQueue队列,而此时 PhantomReference所指向的对象并没有被GC回收,而是要等到ReferenceQueue被你真正的处理后才会被回收。虚引用的用法:
Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue); // 调用phanRef.get()不管在什么情况下会一直返回null Object objg = phanRef.get(); // 如果obj被置为null,当GC发现了虚引用,GC会将phanRef插入进我们之前创建时传入的refQueue队列 // 注意,此时phanRef所引用的obj对象,并没有被GC回收,在我们显式地调用refQueue.poll返回phanRef之后 // 当GC第二次发现虚引用,而此时JVM将phanRef插入到refQueue会插入失败,此时GC才会对obj进行回收 Reference<? extends Object> phanRefP = refQueue.poll();
看了简单的定义之后,我们结合着代码来测试一下,强引用就不用说了,软引用的描述也很清楚,关键是 “弱引用” 与 “虚引用”。
弱引用:
public static void main(String[] args) throws InterruptedException { Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); WeakReference<Object> weakRef = new WeakReference<Object>(obj, refQueue); System.out.println(weakRef.get()); System.out.println(refQueue.poll()); obj = null; System.gc(); System.out.println(weakRef.get()); System.out.println(refQueue.poll()); }
由于System.gc()是告诉JVM这是一个执行GC的好时机,但具体执不执行由JVM决定,因此当JVM决定执行GC,得到的结果便是(事实上这段代码一般都会执行GC):
java.lang.Object@de6ced
null
null
java.lang.ref.WeakReference@1fb8ee3
从执行结果得知,通过调用weakRef.get()我们得到了obj对象,由于没有执行GC,因此refQueue.poll()返回的 null,当我们把obj = null;此时没有引用指向堆中的obj对象了,这里JVM执行了一次GC,我们通过weakRef.get()发现返回了null,而 refQueue.poll()返回了WeakReference对象,因此JVM在对obj进行了回收之后,才将weakRef插入到refQueue 队列中。
虚引用:
public static void main(String[] args) throws InterruptedException { Object obj = new Object(); ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue); System.out.println(phanRef.get()); System.out.println(refQueue.poll()); obj = null; System.gc(); System.out.println(phanRef.get()); System.out.println(refQueue.poll()); }
同样,当JVM执行了GC,得到的结果便是:
null
null
null
java.lang.ref.PhantomReference@1fb8ee3
从执行结果得知,我们先前说的没有错,phanRef.get()不管在什么情况下,都会返回null,而当JVM执行GC发现虚引用之后,JVM 并没有回收obj,而是将PhantomReference对象插入到对应的虚引用队列refQueue中,当调用refQueue.poll()返回 PhantomReference对象时,poll方法会先把PhantomReference的持有队列 queue(ReferenceQueue<? super T>)置为NULL,NULL对象继承自ReferenceQueue,将enqueue(Reference paramReference)方法覆盖为return false,而此时obj再次被GC发现时,JVM再将PhantomReference插入到NULL队列中便会插入失败返回false,此时GC便会回收obj。事实上通过这段代码我们也的却看不出来obj是否被回收,但通过 PhantomReference 的javadoc注释中有一句是这样写的:
Once the garbage collector decides that an object obj
is phantom-reachable, it is being enqueued on the corresponding queue, but its referent is not cleared. That is, the reference queue of the phantom reference must explicitly be processed by some application code.
翻译一下(这句话很简单,我相信很多人应该也看得懂):
一旦GC决定一个“obj”是虚可达的,它(指PhantomReference)将会被入队到对应的队列,但是它的指代并没有被清除。也就是说,虚引用的引用队列一定要明确地被一些应用程序代码所处理。
弱引用与虚引用的用处
软引用很明显可以用来制作caching和pooling,而弱引用与虚引用呢?其实用处也很大,首先我们来看看弱引用,举个例子:
class Registry { private Set registeredObjects = new HashSet(); public void register(Object object) { registeredObjects.add( object ); } }
所有我添加进 registeredObjects 中的object永远不会被GC回收,因为这里有个强引用保存在registeredObjects里,另一方面如果我把代码改为如下:
class Registry { private Set registeredObjects = new HashSet(); public void register(Object object) { registeredObjects.add( new WeakReference(object) ); } }
现在如果GC想要回收registeredObjects中的object,便能够实现了,同样在使用HashMap如果想实现如上的效果,一种更好的实现是使用WeakHashMap。
而虚引用呢?我们先来看看javadoc的部分说明:
Phantom references are useful for implementing cleanup operations that are necessary before an object gets garbage-collected. They are sometimes more flexible than the finalize()
method.
翻译一下:
虚引用在实现一个对象被回收之前必须做清理操作是很有用的。有时候,他们比finalize()方法更灵活。
很明显的,虚引用可以用来做对象被回收之前的清理工作。
package com.bjsxt.others.three; import java.lang.ref.WeakReference; /** * 引用分类:强、软、弱、虚 * 强与弱引用 * @author Administrator * */ public class RefDemo { /** * @param args */ public static void main(String[] args) { //字符串常量池 String str =new String("bjsxt is very good"); //弱引用 管理 对象 WeakReference<String> wr =new WeakReference<String>(str); System.out.println("gc运行前:"+wr.get()); //断开引用 str =null; //通知回收 System.gc(); System.runFinalization(); //对象被回收 System.out.println("gc运行后:"+wr.get()); } public static void testStrong(){ //字符串常量池 共享(不能回收) String str ="bjsxt is very good"; //弱引用 管理 对象 WeakReference<String> wr =new WeakReference<String>(str); System.out.println("gc运行前:"+wr.get()); //断开引用 str =null; //通知回收 System.gc(); System.runFinalization(); System.out.println("gc运行后:"+wr.get()); } }
package com.bjsxt.others.three; import java.util.WeakHashMap; /** * WeakHashMap 键为弱类型,gc运行立即回收 * @author Administrator * */ public class WeakHashMapDemo { /** * @param args */ public static void main(String[] args) { WeakHashMap<String,String> map =new WeakHashMap<String,String>(); //测试数据 //常量池对象,不会回收 map.put("abc", "a"); map.put("d", "test"); //gc运行 已被回收 map.put(new String("bjsxt"), "c"); map.put(new String("dsf"), "d"); //通知回收 System.gc(); System.runFinalization(); System.out.println(map.size()); } }
package com.bjsxt.others.three; import java.util.IdentityHashMap; /** * IdentityHashMap 键比较地址去重 * @author Administrator * */ public class IdentityHashMapDemo { /** * @param args */ public static void main(String[] args) { IdentityHashMap<String ,String> map =new IdentityHashMap<String,String>(); //常量池中的"a" map.put("a", "a1"); map.put("a", "a2"); System.out.println(map.size()); map.put(new String("a"), "a3"); map.put(new String("a"), "a4"); System.out.println(map.size()); } }
package com.bjsxt.others.three; import java.util.EnumMap; /** * EnumMap要求键为枚举 * @author Administrator * */ public class EnumMapDemo { /** * @param args */ public static void main(String[] args) { EnumMap<Season,String> map =new EnumMap<Season,String>(Season.class); //存放值 map.put(Season.SPRING, "春困"); map.put(Season.SUMMER, "夏无力"); map.put(Season.AUTUMN, "秋乏"); map.put(Season.WINTER, "冬眠"); System.out.println(map.size()); } } //季节 enum Season{ SPRING,SUMMER,AUTUMN,WINTER }
package com.bjsxt.others.synread; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * 使用Collections管理同步 容器 * synchronizedList() synchronizedSet() synchronizedMap() * @author Administrator * */ public class Demo01 { /** * @param args */ public static void main(String[] args) { List<String> list =new ArrayList<String>(); list.add("a"); list.add("b"); //list可以同步 List<String> synList =Collections.synchronizedList(list); System.out.println("线程安全的list制作完毕"); } }
package com.bjsxt.others.synread; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * 只读设置 * emptyXxx() 空的不可变的集合 * 1、emptyList() * emptyMap() * emptySet() 2、singletonXxx() 一个元素不可变的集合 singleton(T o) singletonList(T o) singletonMap(K key, V value) 3、unmodifiableXxx() 不可变容器 unmodifiableList(List<? extends T> list) unmodifiableSet(Set<? extends T> s) unmodifiableMap(Map<? extends K,? extends V> m) * @author Administrator * */ public class Demo02 { /** * @param args */ public static void main(String[] args) { Map<String,String> map =new HashMap<String,String>(); map.put("test", "test"); map.put("bjsxt", "bjsxt"); //只读控制 Map<String,String> map2 =Collections.unmodifiableMap(map); //map2.put("a", "a"); //不能操作 System.out.println(map2.size()); //一个元素的容器测试 List<String> list =Collections.singletonList(new String()); list.add("test"); //list.add("bjsxt"); //只能包含一个元素的容器 } public static Set<String> oper(Set<String> set){ if(null==set){ return Collections.EMPTY_SET; //外部获取避免NullPointerException } //操作 return set; } }