Tinking in java 琐碎知识点之集合(容器)
来源:互联网 发布:复利农场源码 编辑:程序博客网 时间:2024/05/21 10:38
1、Iterator必须依附于Collection接口的对象,Iterator本身不提供盛装对象的能力。Collectionname.iterator()方法获得Iterator接口实现类的对象
2、除了使用Iterator遍历Collection集合里的元素,也可以使用foreach循环(注意类型转换)
3、Set接口不允许包含重复元素(根据equals方法判断),而Collection没有此限制。Set接口的两个实现类HashSet是使用的哈希算法决定元素的存储位置,而treeSet使用的是红黑树算法。
4、Object类中定义了hashCode和equals方法,equals方法按照内存地址比较两个对象是否相等,hashCode方法返回值是根据内存地址计算出来的,所以同一个对象hashCode一样。HashSet是通过equas方法和hashCode方法判断两个元素是否相等的,将一个对象放入HashSet中时,HashSet会调用对象的的hashCode方法获得哈希码,再根据这个哈希码计算出对象在集合中存放的位置。因此如果重写了对应类的equals方法则也应该重写hashCode方法,保证如果2个对象通过equals比较相等那这两个对象的hashCode也应该一样,否则HashSet无法正常工作。
(即使两个对象equals方法返回true而hashCode不同也可以添加成功,使HashSet无法正常工作)
5、TreeSet集合是SortSet接口的唯一实现,TreeSet集合里的元素处于排序状态。试图把一个对象添加进TreeSet时,则该对象的类必须实现comparable接口,因为TreeSet会调用集合的元素的compareTo(Object obj)方法来比较元素之间的大小关系。
TreeSet自然排序是根据元素的大小以升序排序,也可以使用定制排序,即不用将类实现Comparable接口了,直接在创建TreeSet集合对象时提供一个Comparator对象作为TreeSet构造器参数,由该Comparator对象实现集合元素的排序逻辑。
6、compareTo(Object obj)方法返回一个整数值,如果obj1.compareTo(obj2)返回0,则表明这两个对象相等。返回一个正整数则表明obj1>obj2,如果返回一个负整数,则obj1<obj2
7、集合里的元素总是引用,但习惯上把被引用的对象称为集合元素
8、在实际应用中TreeSet集合里的对象属性被改变了不会重新排序,也就是说排序只是在元素加进集合时。所以最适合用treeSet排序的是不可变类。
9、为了保持Set规则的一致性,即Set集合中的元素总是不重复的,我们应该尽量保证两个对象通过equals方法和compareTo方法比较的结果一致(还要重写hashCode方法)。
10、关于Set的小结
HashSet性能比TreeSet好(特别是添加、查询操作),只有当要一个保持排序的Set时才应该使用TreeSet
EnumSet性能虽好,但是它只能保存同一个枚举类的枚举值作为集合参数
11、List接口
ArrayList和Vector都是List的实现类(Vector老了,虽然它是线程安全的都是也不推荐使用),ArrayList不是线程安全的,得手动控制,
Vector有个Stack子类,可以模拟栈这种数据结构。LinkedList也是一个List的实现类,它是基于链表实现的List
12、LinkedList和ArrayList、Vector的实现机制完全不同,ArrayList、Vector内部以数组的形式来保存集合中的元素,因此随机访问集合元素有较好的性能,而LinkedList内部以链表的形式来保存集合元素,随机访问性能差,但是插入删除元素时性能出色。
13、HashMap和Hashtable都是Map接口的实现类,他们的关系类似于ArrayList和Vector,Hashtable老了,用起来也不方便。另外Hashtable是线程安全的,HashMap是线程不安全的。(即使要使用线程安全的实现类也不必使用HashTable和Vector,有Collections工具)
14、为了在HashMap和Hashtable中存储、获取对象,用作key的对象必须实现hashCode和equals方法。HashMap和Hashtable判断两个key相等的标准是:两个key 通过equals方法返回true,通过hashCode方法返回值相等。而它们判断两个value是否相等则只要通过equals对象返回true即可。
(当重写了一个类的equals方法后,最好也重写一下hashCode方法,以保证一致性)
public class MapTest {public static void main(String[] args) {HashMap<PerId,Person> hm=new HashMap<PerId,Person>();hm.put(new PerId(0001), new Person("周鹏程1",25));hm.put(new PerId(0002), new Person("周鹏程2",25));hm.put(new PerId(0003), new Person("周鹏程3",26));hm.put(new PerId(0004), new Person("周鹏程",27));hm.put(new PerId(0005), new Person("周鹏程",27));System.out.println(hm.containsKey(new PerId(0004)));System.out.println(hm.containsValue( new Person("周鹏程1",25)));System.out.println(hm.remove(new PerId(0001)));for(Object o:hm.keySet()){System.out.println(hm.get(o).name);}}}class Person{String name;int age;public Person(String name,int age){this.name=name;this.age=age;}public boolean equals(Object obj){if(obj==this){return true;}if(obj!=null&&obj.getClass()==Person.class){Person p=(Person)obj;if(p.age==this.age&&p.name==this.name){return true;}}return false;}}class PerId{int id;public PerId(int id){this.id=id;}public boolean equals(Object obj){if(obj==this){return true;}if(obj!=null&&obj.getClass()==PerId.class){PerId p=(PerId)obj;if(p.id==this.id){return true;}}return false;}//假如没有重写hashCode方法将会出现问题public int hashCode(){return id;}}
15、遍历Map中全部key-value对:调用Map对象的keySet方法返回全部key组成的Set对象,再通过遍历Set的元素(get方法获得key对应的 value)就可以遍历Map中所有的key-value对。
16、HashMap、Hashtable保存key的方式和HashSet保存集合元素的方式一至,所以HashMap、Hashtable对key的要求与HashSet对集合元素的要求相同。如果重写了该类的equals方法则应该也重写hashCode方法。
17、与HashSet类似的是,尽量不要使用可变对象作为HashMap、Hashtable的key,如果使用了可变对象,则尽量不要在程序中修改作为key的可变对象。
18、Hashtable有一个实用的子类Properties类,在处理属性文件时特别方便。Properties类可以把Map对象和属性文件关联起来,从而可以把Map对象中的key-value写入属性文件,也可以把属性文件中的属性名、属性值加载到Map对象中。
例程:
import java.io.*;import java.util.*;public class TestProperties {public static void main(String[] args)throws Exception {Properties props=new Properties();props.setProperty("username", "zpc");props.setProperty("password", "123456");//将Properties中的属性保存到a.ini对象中props.store(new FileOutputStream("a.ini"), "comment line(属性文件)");Properties props2=new Properties();props2.setProperty("gender", "male");props2.load(new FileInputStream("a.ini"));System.out.println(props2);}} //输出:{password=123456, gender=male, username=zpc}
19、正如Set接口派生出SortedSet子接口,SortedSet接口有一个TreeSet实现类,Map接口有一个SortedMap子接口,SortedMap也有一个TreeMap实现类。与TreeSet类似,TreeMap也是基于红黑树对TreeMap中的所有key进行排序,从而保证TreeMap中所有key-value对处于有序状态。TreeMap也有自然排序(key所在的类实现Comparable接口、所有key应该是同一个类的对象)和客户化(创建TreeMap时传入一个Comparator对象,该对象负责实现排序逻辑)排序两种方式。
20、IdentityHashMap与HashMap基本相似,只是在处理两个key是否相等时不一样:只有当两个key严格相等(key1==key2)时才会认为两个key相等
21、操作集合工具类Collections提供了一些方法对集合元素进行排序、查询和修改操作,还提供了将集合对象设置成不可变、对集合对象实现同步控制等方法。
public static void main(String[] args) {IdentityHashMap ihm=new IdentityHashMap();ihm.put(new String("语文"),89);ihm.put(new String("语文"),78);ihm.put("java",89);ihm.put("java",89);System.out.println(ihm);}//“java”字符串是字符串直接量,放在缓存,而new的两个对象用==比较不等
21、操作集合工具类Collections提供了一些方法对集合元素进行排序、查询和修改操作,还提供了将集合对象设置成不可变、对集合对象实现同步控制等方法。
//showHand游戏import java.util.*;class ArrayUtils {/** * 定义一个工具方法,工具方法从字符串数组中找到对应的字符串元素的位置 * * @param array * 搜索的数组 * @param target * 搜索的字符串 * @return 目标字符串出现的位置,-1表明找不到 */public static int search(String[] array, String target) {for (int i = 0; i < array.length; i++) {if (array[i] != null && array[i].equals(target)) {return i;}}return -1;}}public class ShowHand {private final int PLAY_NUM = 4;// 限定玩家数量private String[] types = { "\4 ", "\5", "\3", "\6" };//特殊字符,会在控制台打印出方块、草花、红心和黑桃private String[] values = { "2", "3", "4", "5", "6", "7", "8", "9", "10","J", "Q", "K", "A" };// cards存放牌private List<String> cards = new LinkedList<String>();// 用一个数组存放玩家private String[] players = new String[PLAY_NUM];// 每一个玩家都用一个List存放其获得的牌private List<String>[] playersCards = new List[PLAY_NUM];// 初始化,放入扑克牌public void initCards() {for (int i = 0; i < types.length; i++) {for (int j = 0; j < values.length; j++) {cards.add(types[i] + values[j]);}}// 调用集合工具类的方法随机排列Collections.shuffle(cards);}// 初始化玩家,为每个玩家分配用户名public void initPlayer(String... names) {if (names.length < 2 || names.length > PLAY_NUM) {System.out.println("输入玩家数量不对!");return;} else {// 初始化用户for (int i = 0; i < names.length; i++) {players[i] = names[i];}}}// 初始化保存玩家牌的Listpublic void initPlayerCards() {for (int i = 0; i < players.length; i++) {if (players[i] != null && !players.equals("")) {playersCards[i] = new LinkedList<String>();}}}// 写一个输出全部扑克牌的方法public void showAllCards() {for (String card : cards) {System.out.println(card);}}// 给玩家派牌的方法(指定一个最先派牌的玩家)public void deliverCard(String first) {int firstPos = ArrayUtils.search(players, first);//依次给位于指定玩家之后、之前的每个玩家派牌for(int i=firstPos;i<players.length;i++){if(players[i]!=null){playersCards[i].add(cards.get(0));cards.remove(0);}}//为之前的每个玩家派牌for(int i=0;i<firstPos;i++){if(players[i]!=null){playersCards[i].add(cards.get(0));cards.remove(0);}}}//输出玩家手中的牌public void showPlayerCards(){System.out.print("当前牌况:");for(int i=0;i<players.length;i++){if(players[i]!=null){System.out.println("\n"+players[i]+":");for(String card:playersCards[i]){System.out.print (card+"\t");}}}System.out.print("\n");}public static void main(String[] args) {ShowHand sh = new ShowHand();sh.initCards();sh.initPlayer("鸟鹏", "鸟朱");sh.initPlayerCards();sh.showAllCards();System.out.println("*****************");//第一次从玩家鸟鹏开始派牌sh.deliverCard("鸟鹏");sh.showPlayerCards();//第二次从玩家鸟朱开始派牌sh.deliverCard("鸟朱");sh.showPlayerCards();}}
22、泛型:JDK1.5支持的泛型很大程度上是为了让集合能记住其元素的类型,这样会带来许多好处(Java泛型可以保证如果程序在编译的时候没有警告,运行时就不会产生ClassCastException异常,集合中默认存放的都是object对象,取出来还得强制转型,使用泛型就不要了)。
//一个泛型的案例public class Apple<T> {private T info;public Apple() {}public Apple(T info){this.info=info;}public T getInfo(){return info;}public static void main(String[] args){//因为传给T形参的是String实际类型,所以构造器的参数只能是StringApple<String> apple1=new Apple<String>("苹果");System.out.println(apple1.getInfo());System.out.println(apple1.getClass());Apple<Double> apple2=new Apple<Double>(12.9);System.out.println(apple2.getInfo());System.out.println(apple2.getClass());}}//输出//苹果//12.9
泛型数组(Java允许创建无上限的通配符泛型数组):
List<?>[] lsa= new ArrayList<?>[10];Object[] oa=(Object[])lsa;List<Integer> li=new ArrayList<Integer>();li.add(new Integer(7));oa[1]=li;System.out.println("lsa.getClass():"+lsa.getClass());System.out.println("lsa[1].get(0).getClass():"+lsa[1].get(0).getClass());//String s=(String)lsa[1].get(0);//List的get方法Object target=lsa[1].get(0);if(target instanceof String){String s=(String)target;}
23、注意:在使用带了泛型声明的接口、父类之后,在使用这些接口或父类时不能再包含类型形参(方法中的形参只有当定义方法时才使用数据形参,当调用(使用)方法时必须传入实际的数据;与此类似的是:类、接口中的类型参数只有在定义类、接口时才可以使用类型参数,当使用类、接口时应该为类型参数传入实际的类型)。
如上例继承Apple类时可以有两种写法
public class A extends Apple<String>{}
或者直接不写<T>即:public class A extends Apple{}
数组和泛型有所不同,假设Son是Father的一个子类型(子类或者子接口),那么Son[]依然是Father[]的一个子类型,但是C<Son>并不是C<Father>的一个子类型。
24、使用类型通配符
(设定类型通配符的上限)比如List<? extends Shape>表示所有Shape泛型List的父类,List集合的元素要么是Shape类型的要么是Shape的子类型都行(设定类型形参的上限)也可以在定义类时设定类型上限:public class Apple<T extends Number>。
也可以使用泛型方法:
修饰符 <T,S> 返回值类型 方法名(形参列表)
{
//方法体
}
例程:abstract class Shape{public abstract void draw(Canvas c); } class Circle extends Shape{@Overridepublic void draw(Canvas c) {System.out.println("在画布"+c+"画一个圆");}}class Rectangule extends Shape{@Overridepublic void draw(Canvas c) {System.out.println("在画布"+c+"画一个矩形");}}public class Canvas {//同时在画布上绘制多个形状//使用被限制的泛型通配符public void drawAll(List<? extends Shape> shapes){for(Shape s:shapes){s.draw(this);}}public static void main(String[] args) {List<Circle> circleList=new ArrayList<Circle>();List<Rectangule> rectangule=new ArrayList<Rectangule>();circleList.add(new Circle());rectangule.add(new Rectangule());Canvas c=new Canvas();c.drawAll(circleList);c.drawAll(rectangule);}}
0 0
- Tinking in java 琐碎知识点之集合(容器)
- Tinking in java 琐碎知识点之反射
- tinking in java ?
- Thinking In Java琐碎知识点摘要(一)
- Thinking In Java琐碎知识点摘要(二)
- 1.4Tinking in java--适配器
- Thinking in java 琐碎知识点之 I/O流 、对象序列化
- java琐碎的知识点
- java琐碎知识点1
- java琐碎知识点410
- JAVA学习之必备知识点琐碎(一)
- Thinking in java 集合容器
- 疯狂java讲义 琐碎知识点
- 一些琐碎的java知识点
- JAVA集合(容器)类知识点汇总
- Tinking in Java ---Java的NIO和对象序列化
- 1.3Tinking In Java——抽象类接口
- 1.1Tinking In Java——析构函数
- Practice of using spinlock instead of mutex
- gcc参数详解
- 类型转换辅助工具类
- jboss之启动加载过程详解(-)
- OC基础—面向对象思想(思想很重要)
- Tinking in java 琐碎知识点之集合(容器)
- DWR的使用,配置,例子,详解整理
- 五年码农,感慨良多
- 学习笔记 (samba配置、Linux的acl文件授权、widows的net use) [第十二课]
- 金山打字通2013去广告补丁:
- 转(Android 4.4 Kitkat Phone工作流程浅析(一)__概要和学习计划)
- sdasd
- DBCP连接池介绍
- Java数据结构(排序篇)