Java容器
一、List接口
ArrayList,对象加入之后大都是为了取出,而不会长做删除或插入的动作,则使用ArrayList效率会更加好,但是经常在容器里面做删除添加动作,则使用LinkList会更加好(该类是利用链表实现的),故增加了象addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeFast()等,这样适合实现堆栈和队列。
二、Set接口
List容器中允许重复的对象,但是Set容器中的对象都是唯一的,介入Set 容器必须重新定义equals(),hasCode()方法,Set容器有自己一套排序规则,其规则是根据哈希法,所以加入HashSet容器的对象还必须重新定义hasCode()方法.
Set<String> set=new HashSet<String>();
Iterator iterator=set.iterator();
while(iterator.hasNext()){ iterator.next() };
也可以利用加强型进行访问元素:for(String name : set){ System.out.println(name); }
如果想要以加入的顺序显示,则可以用LinkedHashSet,此类是HashSet的子类,它在内部类实现时使用哈希玛进行排序但是在迭代的行为上像LinkList那样.
TreeSet实现了Set接口和SortSet接口,SortSet提供的相关方法让您有序的去处对应位置的对象,像first()、last()等方法,TreeSet是J2SE中唯一实现了SortSet接口的类,它使用了红黑树结构来加入对象将进行排序。如果对对象有自己的一套排序,要定义一个实现java.util,Comparator接口的对象,要实现compare()方法.
三、Map接口
Map接口的对象会将键(Key)映射至值(Value),值指的是要存入Map容器的对象,其对象不能有重复的键,Map拥有
自己的排序机制。
HashMap实现Map接口,在内部实现使用了哈希法,如果在迭代的时候想要以添加的顺序
来排序,则可以用HashMap子类LinkedHashMap。
其访问对象的代码:
Map<String,String> map=new HashMap<String,String>();
for(String value :map.values){
System.out.println(value);
}
TreeMap实现Map接口和SortMap接口,SortMap提供相关的方法让你有序地取出对应位置的对象,像firstKey(),lastKey()等方法,TreeMap是唯一实现SortedMap接口的类,它使用了红黑树结构来对加入的对象进行排序。
四、hashCode的作用
非常重要
小心内存泄露问题
用容器的时候为什么要覆盖equals()和hasCode()方法?上面是解释的原因
什么时候需要覆盖hashCode方法?
下面用例子进行证明:
package cn.itcast.day1;
import java.util.Date;
public class ReflectPoint {
private Date birthday = new Date();
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcast";
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
@Override
public String toString(){
return str1 + ":" + str2 + ":" + str3;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
package cn.itcast.day1;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
public class ReflectTest2 {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
/*getRealPath();//金山词霸/内部
一定要记住用完整的路径,但完整的路径不是硬编码,而是运算出来的。*/
//InputStream ips = new FileInputStream("config.properties");
//InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");
//InputStream ips = ReflectTest2.class.getResourceAsStream("resources/config.properties");
/* InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resources/config.properties");
Properties props = new Properties();
props.load(ips);
ips.close();
String className = props.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();
*/
Collection collections = new HashSet();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
//pt1.y = 7;
//collections.remove(pt1);
System.out.println(collections.size());
}
}
也就是说如果突然修改对象hashCode的值pt1.y=7,此容器想要移出这个对象,这个是办不到的,因此导致了内存的泄露
六、如何利用反射读取配置文件?用类加载器的方式管理资源和配置文件
InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");
InputStream ips = ReflectTest2.class.getResourceAsStream("resources/config.properties")这个是第二种方式寻找配置文件.此文件假设存放在cn/itcast/day1/resources/config.properties
cn/itcast/day1/config.properties这个是所在的包中的文件路径,ReflectTest2类是在本类中找到装载器并加载所在的文件,这里注意类加载器再在class文件是从自己建的项目的路径开始加载,所以在寻找配置文件的时候一定要注意要加上所放配置文件的相对路径。所以在找文件的时候是在calsspath路径下找此文件。
Properties props = new Properties();
props.load(ips);
ips.close();
String className = props.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();
这样就能够根据className字符串动态的构建对象.
读取的文件格式为:className=java.util.ArrayList
补充:
容器类
Java容器类包含List、ArrayList、Vector及map、HashTable、HashMap
ArrayList和HashMap是异步的,Vector和HashTable是同步的,所以Vector和HashTable是线程安全的,而 ArrayList和HashMap并不是线程安全的。因为同步需要花费机器时间,所以Vector和HashTable的执行效率要低于 ArrayList和HashMap。
Collection
├List 接口
│├LinkedList 链表
│├ArrayList 顺序结构动态数组类
│└Vector 向量
│ └Stack 栈
└Set
Map
├Hashtable
├HashMap
└WeakHashMap List接口
List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
和下面要提到的Set不同,List允许有相同的元素。
除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素, 还能向前或向后遍历。
实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。
ArrayList类
ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法 并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
和LinkedList一样,ArrayList也是非同步的(unsynchronized)。
Map接口
请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个 value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。
HashMap类
HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap 的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。
所谓Java容器就是存放其他的容器的对象或器皿的工具。
Collection接口是Java容器的根接口,所有Java容器都是从这继承此接口。
Collection分为Set接口和List接口,还有一种就是Map接口。
Set接口存放的数据是无序且不可以重复的数据。
List接口是存放有序且可以重复的数据。
Map接口是存放键值对的形式。
转载于:https://blog.51cto.com/wuqinglong/1431779