Java面向对象 集合(下)



知识概要:

              (1)Map集合的体系结构

(2)Map集合的方法

(3)HashMap TreeMap

(4)集合框架中的常用工具类

(5)高级for循环

Map集合的体系结构

Map

              |--Hashtable:   底层是哈希表数据结构,不可以存入null键null值。   该集合是线程同步的。jdk1.0.效率低。

              |--HashMap: 底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代  

              |--TreeMap:  底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。

Map集合的常用方法

1,添加。

put(K key, V value)

       putAll(Map<? extends K,? extends V> m)

2,删除。

clear()

       remove(Object key)

3,判断。

containsValue(Object value)

      containsKey(Object key)

      isEmpty()

4,获取。

get(Object key)

     size()

     values()

import java.util.*;
class MapDemo
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>(); //添加元素,添加元素,如果出现添加时,相同的键。那么后添加的值会覆盖原有键对应值。
//并put方法会返回被覆盖的值。
System.out.println("put:"+map.put("01","zhangsan1"));
System.out.println("put:"+map.put("01","wnagwu"));
map.put("02","zhangsan2");
map.put("03","zhangsan3"); System.out.println("containsKey:"+map.containsKey("022"));
//System.out.println("remove:"+map.remove("02")); System.out.println("get:"+map.get("023")); map.put("04",null);
System.out.println("get:"+map.get("04"));
//可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。 //获取map集合中所有的值。
Collection<String> coll = map.values(); System.out.println(coll);
System.out.println(map); }
}

map集合的两种取出方式:



 1,Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。

       所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。

       Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。

2,Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,

      而这个关系的数据类型就是:Map.Entry

Entry其实就是Map中的一个static内部接口。

      为什么要定义在内部呢?

      因为只有有了Map集合,有了键值对,才会有键值的映射关系。

      关系属于Map集合中的一个内部事物。

      而且该事物在直接访问Map集合中的元素。

import java.util.*;

class MapDemo2
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>(); map.put("02","zhangsan2");
map.put("03","zhangsan3");
map.put("01","zhangsan1");
map.put("04","zhangsan4"); //将Map集合中的映射关系取出。存入到Set集合中。
Set<Map.Entry<String,String>> entrySet = map.entrySet() Iterator<Map.Entry<String,String>> it = entrySet.iterator(); while(it.hasNext())
{
Map.Entry<String,String> me = it.next();
String key = me.getKey();
String value = me.getValue(); System.out.println(key+":"+value); } /*
//先获取map集合的所有键的Set集合,keySet();
Set<String> keySet = map.keySet(); //有了Set集合。就可以获取其迭代器。
Iterator<String> it = keySet.iterator(); while(it.hasNext())
{
String key = it.next();
//有了键可以通过map集合的get方法获取其对应的值。
String value = map.get(key);
System.out.println("key:"+key+",value:"+value);
} */ }
}
<strong>/*
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。
保证学生的唯一性 1,描述学生。 2,定义map容器。将学生作为键,地址作为值。存入。 3,获取map集合中的元素。 */ import java.util.*;
class Student implements Comparable<Student>
{
private String name;
private int age;
Student(String name,int age)
{
this.name = name;
this.age = age;
} public int compareTo(Student s)
{
int num = new Integer(this.age).compareTo(new Integer(s.age)); if(num==0)
return this.name.compareTo(s.name);
return num;
} public int hashCode()
{
return name.hashCode()+age*34;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配"); Student s = (Student)obj; return this.name.equals(s.name) && this.age==s.age; }
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String toString()
{
return name+":"+age;
}
} class MapTest
{
public static void main(String[] args)
{
HashMap<Student,String> hm = new HashMap<Student,String>(); hm.put(new Student("lisi1",21),"beijing");
hm.put(new Student("lisi1",21),"tianjin");
hm.put(new Student("lisi2",22),"shanghai");
hm.put(new Student("lisi3",23),"nanjing");
hm.put(new Student("lisi4",24),"wuhan"); //第一种取出方式 keySet Set<Student> keySet = hm.keySet(); Iterator<Student> it = keySet.iterator(); while(it.hasNext())
{
Student stu = it.next();
String addr = hm.get(stu);
System.out.println(stu+".."+addr);
} //第二种取出方式 entrySet
Set<Map.Entry<Student,String>> entrySet = hm.entrySet(); Iterator<Map.Entry<Student,String>> iter = entrySet.iterator(); while(iter.hasNext())
{
Map.Entry<Student,String> me = iter.next();
Student stu = me.getKey();
String addr = me.getValue();
System.out.println(stu+"........."+addr);
}
}
}
</strong>

 集合工具类

集合框架的工具类。

            Collections:集合框架的工具类。里面定义的都是静态方法。
Collections和Collection有什么区别?


Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。它有两个常用的子接口,

           List:对元素都有定义索引。有序的。可以重复元素。

           Set:不可以重复元素。无序。

Collections是集合框架中的一个工具类。该类中的方法都是静态的

         提供的方法中有可以对list集合进行排序,二分查找等方法。

         通常常用的集合都是线程不安全的。因为要提高效率。

         如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。

Collections.shuffle(list);                                                将集合打乱顺序

   Collections.reverseOrder(new StrLenComparator())  将集合的比较器反向比较
  Collections.replaceAll(list,"aaa","pp");                        将集合中“aaa”替换成“pp”
  Collections.reverse(list);                                                将集合反向
  Collections.fill(list,"pp");                                                将集合全部替换成pp
  Collections.sort(list,new StrLenComparator());           将集合按照指定比较器排序

Arrays:

用于操作数组的工具类。

    里面都是静态方法。           
asList:将数组变成list集合

把数组变成list集合有什么好处?

 

  可以使用集合的思想和方法来操作数组中的元素。

注意:将数组变成集合,不可以使用集合的增删方法。

  因为数组的长度是固定。

如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。

  如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。

集合变数组。

Collection接口中的toArray方法。

<strong>/*
集合变数组。
Collection接口中的toArray方法。 */
import java.util.*;
class CollectionToArray
{
public static void main(String[] args)
{
ArrayList<String> al = new ArrayList<String>(); al.add("abc1");
al.add("abc2");
al.add("abc3"); /*
1,指定类型的数组到底要定义多长呢?
当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。
当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。剩余的数组位置为null
所以创建一个刚刚好的数组最优。 2,为什么要将集合变数组?
为了限定对元素的操作。不需要进行增删了。 */ String[] arr = al.toArray(new String[al.size()]); System.out.println(Arrays.toString(arr)); }
}
</strong>




高级for循环
    
   格式:

      for(数据类型 变量名 : 被遍历的集合(Collection)或者数组)

     {

    

     }


    对集合进行遍历。

   只能获取集合元素。但是不能对集合进行操作。
   迭代器除了遍历,还可以进行remove集合中元素的动作。

   如果是用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
   传统for和高级for有什么区别呢?
   高级for有一个局限性。必须有被遍历的目标。
   建议在遍历数组的时候,还是希望是用传统for。因为传统for可以定义脚标。
import java.util.*;

class ForEachDemo
{
public static void main(String[] args)
{ ArrayList<String> al = new ArrayList<String>(); al.add("abc1");
al.add("abc2");
al.add("abc3"); for(String s : al)
{
//s = "kk";
System.out.println(s);
} System.out.println(al);
/*
Iterator<String> it = al.iterator(); while(it.hasNext())
{
System.out.println(it.next());
}
*/ int[] arr = {3,5,1}; for(int x=0; x<arr.length; x++)
{
System.out.println(arr[x]);
}
for(int i : arr)
{
System.out.println("i:"+i);
} HashMap<Integer,String> hm = new HashMap<Integer,String>(); hm.put(1,"a");
hm.put(2,"b");
hm.put(3,"c"); Set<Integer> keySet = hm.keySet();
for(Integer i : keySet)
{
System.out.println(i+"::"+hm.get(i));
} // Set<Map.Entry<Integer,String>> entrySet = hm.entrySet();
// for(Map.Entry<Integer,String> me : entrySet) for(Map.Entry<Integer,String> me : hm.entrySet())
{
System.out.println(me.getKey()+"------"+me.getValue());
} }
}
0

首先要明白一点:加入Set里面的元素必须定义equals()方法以确保对象的唯一性。



第一个问题:TreeSet是怎么实现有序的,它是按什么规则排序的?

TreeSet的底层实现是采用红-黑树的数据结构,采用这种结构可以从Set中获取有序的序列,但是前提条件是:元素必须实现Comparable接口,该接口中只用一个方法,就是compareTo()方法。当往Set中插入一个新的元素的时候,首先会遍历Set中已经存在的元素(当然不是采用顺序遍历,具体采用什么方法,建议自己去看看源码),并调用compareTo()方法,根据返回的结果,决定插入位置。进而也就保证了元素的顺序。





第二个问题:它们怎么保证元素的不重复,是根据什么判断两个元素相同而不再添加的呢?

上面已经说过,加入Set里面的元素必须定义自己的equals()方法,但是对于良好的设计风格,最好在覆盖equals()方法的同时,也覆盖hashCode()方法,当然,对于TreeSet而言不用覆盖hashCode()方法也可。请记住:覆盖hashCode()方法的目的,只有一个原因就是提高效率。



在往Set中插入新的对象时,首先会用该对象的hashCode()与已经存在对象的hashCode()做比较,如果相等,那就不能插入,如果不等,才会调用equals()方法,如果equals结果为true,说明已经存在,就不能再插入,如果为false,可以插入。



注:如果没有覆盖hashCode()方法,那就是只比较equals().对两个对象equals运算,是判断两个对象是否相等的关键







Java面向对象 集合(下)的更多相关文章

  1. Java面向对象 集合(上)

     Java面向对象  集合(上) 知识概要:             (1)体系概述 (2)共性方法 (3)迭代器 (4)list集合 (5)Set 集合 体系概述:              集 ...

  2. Java面向对象 集合(中)

     Java面向对象 集合(中) 知识概要:                   (1)泛型的体系概念 (2)泛型的特点 (3)自定义泛型类 泛型的体系概念           泛型:JDK1.5版 ...

  3. java面向对象程序设计(下)-枚举类

    在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有4个对象;再比如行星类,目前只有8个对象,这些实例有限而且固定的类,在Java中被称为枚举类 JDK1.5新增了一个enum关键字,(它与 ...

  4. java面向对象程序设计(下)-接口的定义

    抽象类是从多个类中抽象出来的模板,如果将这种抽象进行得更加彻底,则可以提炼出一种更加特殊的"抽象类"-接口(interface),Java9对接口进行了改进,允许在接口中定义默认方 ...

  5. Java面向对象(下)作业

    首先我把题目先列到这里,可以仔细看一下题. (1)设计一个名为Geometric的几何图形的抽象类,该类包括: ①两个名为color.filled属性分别表示图形颜色和是否填充. ②一个无参的构造方法 ...

  6. 第三章 Java面向对象(下)

    3.1.抽象类 概述:在做子类共性功能抽取时,有些方法在父类中并没有具体的体现,这个时候就需要抽象类了 格式:public abstract class 类名 {} 语法特点: 抽象类和抽象方法必须使 ...

  7. Java面向对象 网络编程 下

    Java面向对象 网络编程  下 知识概要:                   (1)Tcp 练习 (2)客户端向服务端上传一个图片. (3) 请求登陆 (4)url 需求:上传图片. 客户端:   ...

  8. Java面向对象 继承(下)

     Java面向对象   继承(下) 知识概要:               (1)抽象类 1.1 抽象类概述                            1.2 抽象类的特点       ...

  9. Java面向对象作业-用接口方式测试向下转型

    Java面向对象作业-用接口方式测试向下转型 根据视频的里实例 我们直接修改Test2测试方法: package com.java1234.chap03.sec13; public class Tes ...

随机推荐

  1. IBM与麻省理工学院联合建立AI实验室 承诺投资2.4亿美元

         IBM和麻省理工学院将通过今天宣布的一个新的联合实验室共同努力,对人工智能进行广泛的研究.麻省理工学院IBM沃森AI实验室将重点关注四个研究支柱:开发AI算法,使用物理学来创建AI计算的新硬 ...

  2. 查看numpy.ndarray的数据类型

    使用ndarray数据时,如果希望知道数据的类型和维数,可以按照以下方法: Xxx.dtype  #xxx表示一个ndarray类型的变量,返回ndarray的数据类型 Xxx.shape  #xxx ...

  3. shell脚本进阶之循环判断

    p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; f ...

  4. 转:【Java并发编程】之十六:深入Java内存模型——happen-before规则及其对DCL的分析(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17348313 happen-before规则介绍 Java语言中有一个"先行发生 ...

  5. 201521123050 《Java程序设计》第13周学习总结

    1. 本周学习总结 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 对比可以看出 ...

  6. 201521123119 《Java程序设计》第13周学习总结

    1. 本周学习总结 Q以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 Q1. 网络基础 Q1.1 比较ping www.baidu.com与ping cec. ...

  7. 201521123031 《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 1.将Student对象(属性:int id, String name,int age,dou ...

  8. 参加IMWebConf 2017 前端开发者大会是什么体验?

    周六作为特邀讲师之一参加了IMWebConf 2017 前端开发者大会的主题演讲,主题为<WebAssembly:面向未来的web开发技术>.本次大会质量非常高,来自国内外的技术专家带了很 ...

  9. Java: 类继承中 super关键字

    super 关键字的作用有两个: 1)在子类中调用超类的构造器,完成实例域参数的初始化,调用构造器的语句只能作为另一个构造器(通常指的是子类构造器)的第一条语句出现, 2)在子类中调用超类的方法,如: ...

  10. Mybatis第七篇【resultMap、resultType、延迟加载】

    resultMap 有的时候,我们看别的映射文件,可能看不到以下这么一段代码: <resultMap id="userListResultMap" type="us ...