1.
之前我们学过 数组:
数组的特点:
01. 长度一旦被定义,不允许被改变
02. 在内存中开辟一连串连续的空间! 那么现在有一个需求:
让我们定义一个数组 来 保存 新闻信息!!!
问题:
01.如果定义一个数组 长度为50
今天的新闻数量只有10条! 那么有40个空间被浪费掉了!
02.今天的新闻数量只有100条! 那么无法存放多余的50条信息! 在程序的运行过程中,我们不知道需要多少个对象的时候,我们首选集合!!! 集合框架!
Vector 线程安全的,但是性能低!
List
Set
Map java中的集合框架是 jdk给我们提供好的一些列接口或者类的集合!
他们都存在于 java.util包中! public interface List<E> extends Collection<E>
public interface Set<E> extends Collection<E> public interface Map<K,V> 通过观看底层代码 得知: List Set 接口都 继承了Collection接口!
Collection接口中存储的都是不唯一(可以重复),无序的对象!
List接口中存储的都是不唯一(可以重复),有序(插入顺序)的对象!
常用的实现类
ArrayList
LinkedList
Set接口中存储的都是唯一(不可以重复),无序的对象!
常用的实现类
HashSet
TreeSet Map是单独的接口!
Map接口存储的是一组键值对(key , value)!key是不允许重复的!
常用的实现类
HashMap
TreeMap 接口不能被实例化!
所以我们刚才看到的 List Set Map 都应该有对应的实现类!
我们使用的时候肯定是使用实现类!或者使用多态!
父类引用指向子类的对象! 学数组的时候有没有工具类??? Arrays 现在集合中 也有工具类 Collections /**
* ArrayList和LinkedList的区别
* ArrayList:采用数组的形式来保存数据!这些数据被放在内存中开辟连续的空间!
* 每个数据的位置都有下标!
* 比如说:
* 现在集合长度为50! 现在想删除下标为2的元素!
* 删除之后,底层还要做什么操作?
* 下标为2之后的元素都要前移??
*
* 现在想在下标为3的位置 新增 元素!
* 下标3的元素之后的数据全部后移??
* 所以 新增,删除效率慢!
* 因为是数组结构,所以遍历,查询效率高!
*
* LinkedList:链表式结构!存储在集合中的每个对象都存放在相互独立的空间!
* 比如说:
* 现在集合长度为50!
* 第1个元素记录第2个元素的位置
* 第2个元素记录第3个元素的位置
* 。。。。
* 第49个元素记录第50个元素的位置
* 我们想删除第3个元素!
* 只需要让 第2个元素记录第4个元素的位置!
* 之后的元素有影响吗? 没有
*
* 在第2个元素和第3个元素之间新增一个元素x
* 这时候只需要 第2个元素 记录x的位置
* x记录第三个元素的位置
* 新增,删除效率高!
* 因为没有下标,所以查询遍历的效率低!
*
*/
2.ArrayList
public class ArrayTest {

    public static void main(String[] args) {

        int nums[] = new int[5];
nums[0] = 1;
nums[1] = 1;
nums[2] = 1;
nums[3] = 1;
nums[4] = 1;
nums[5] = 1; // ArrayIndexOutOfBoundsException } }

ArrayList

import java.util.ArrayList;

public class ArrayListTest {

    public static void main(String[] args) {
/**
* 在程序运行过程中,不确定有多少个对象 加入到 集合中!
* 使用集合框架!
* 现在 我们想 新增 LinkedList
* 现在 我们想 查询 ArrayList
* 上述的两个类 都是 List接口的 实现类!
*
* 01. ArrayList 底层是实现了一个可变长度(自动扩容)的数组!
* 在内存中也是分配连续的空间!
* 遍历元素和随机访问元素的时候 性能高! 因为有下标!
*/ // 01创建一个ArrayList集合
ArrayList list = new ArrayList();
/**
* 02. 向集合中增加元素
* 为什么可以存放这么多数据类型
* 因为底层就是一个Object[]数组 默认的初始长度=10
* Object 所有类的父类,所以可以存放任何类型!
*
*/
list.add(1);
list.add("2");
list.add(12.5);
list.add('5');
list.add('1');
list.add(null);
list.add(7);
list.add(8);
list.add(9);
list.add(10);
list.add(11); // 自动扩充 原来长度的1.5倍
// 03.输出集合的长度 实际使用的位置个数
System.out.println(list.size());
// 04. 查询集合中下标是3 的元素
System.out.println("集合中下标是3 的元素:" + list.get(3));
// 05. 删除下标为5的元素
list.remove(5);
System.out.println("删除元素之后的长度:" + list.size());
// 06.查询集合中是否包含某个元素
System.out.println("集合中是否包含12.5:" + list.contains(12.5));
}
}

ArrayListTest

3.LinkedList

import java.util.LinkedList;

public class LinkedListTest {

    public static void main(String[] args) {
/**
* 02.LinkedList :采用的是链表式存储结构! 插入和删除的效率高!
*
* 谁能告诉我???
* 为什么不使用
* List list = new LinkedList(); 父类的引用指向了子类的对象!
*
* LinkedList list= new LinkedList(); 使用这种方式!
*
* List 和 LinkedList 什么关系?
* 001.LinkedList继承了List!
* List接口中有的方法LinkedList有吗?
* 002. 有
* LinkedList中有特有的方法, List接口中有吗? !!!!
* 003. 没有!
*
*/
// 创建集合
LinkedList list = new LinkedList();
// 创建新闻对象
News news1 = new News(1, "新闻1");
News news2 = new News(2, "新闻2");
News news3 = new News(3, "新闻3");
News news4 = new News(4, "新闻4"); // 集合中保存新闻信息
list.add(news1);
list.addFirst(news2);
list.add(news3);
list.addFirst(news4); for (Object object : list) {
News news = (News) object;
System.out.println(news);
} // 删除最后一个对象
list.removeLast();
System.out.println("*********************");
for (Object object : list) {
News news = (News) object;
System.out.println(news);
}
// 查询某个元素在集合中的位置
System.out.println("news4在集合中的位置:" + list.indexOf(news4)); }
}

LinkedListTest

4.Iterator

import java.util.ArrayList;
import java.util.Iterator; /*
* 新闻实体类
*/
public class News { private int id; // 新闻编号
private String title; // 新闻标题 public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public News(int id, String title) {
super();
this.id = id;
this.title = title;
} public News() {
super();
} @Override
public String toString() {
return "News [id=" + id + ", title=" + title + "]";
} public static void main(String[] args) {
// 创建一个集合
ArrayList list = new ArrayList();
// 创建新闻对象
News news1 = new News(1, "新闻1");
News news2 = new News(2, "新闻2");
News news3 = new News(3, "新闻3");
News news4 = new News(4, "新闻4"); // 集合中保存新闻信息
list.add(news1);
list.add(news2);
list.add(news3);
list.add(news4);
// list.add("aaaaaa");ClassCastException 类型转换 // 01.第1种方式 遍历 for循环
for (int i = 0; i < list.size(); i++) {
News news = (News) list.get(i); // 必须向下转型
System.out.println(news);
}
System.out.println("*****************************");
// 02.第2种方式 遍历 for增强循环
for (Object n : list) {
News news = (News) n; // 必须向下转型
System.out.println(news);
}
System.out.println("*****************************");
/**
* 03.第3种方式 遍历 iterator 迭代器循环
*
* 001.hasNext() :判断我们的集合中是否还有元素
* 002.next():获取集合中的下一个元素
* 003.remove():删除元素
*/
// 清空整个集合
list.clear(); // 底层的数组 长度还是之前的长度!
// 判断集合是否为空
System.out.println("集合是否为空:" + list.isEmpty());
Iterator it = list.iterator();
while (it.hasNext()) {
News news = (News) it.next();// 获取元素
System.out.println(news);
} } }

Iterator

5.Set

import java.util.HashSet;
import java.util.Set; public class SetTest { public static void main(String[] args) {
/**
* Set :
* 01.存储的是唯一(不能重复) 无序的数据!
* 02.HashSet是常用的实现类
* 03.存放的是对象的引用
*/ Set set = new HashSet();
set.add(1);
set.add("1");
set.add('1');
set.add(null);
System.out.println(set.size()); // 输出集合的大小 4 Set set2 = new HashSet();
set2.add(1);
set2.add(1);
set2.add(1);
System.out.println(set2.size()); // 输出集合的大小 1 /**
* 通过观看底层代码得知:
private transient HashMap<E,Object> map;
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
01.HashSet 类中 有一个属性是 map ,值类型是 HashMap
02.我们在使用add(e) ,其实是调用了map.put(e,PRESENT)
把e当成了map的key值!
因为Map的key是唯一的! 所以我们的hashSet存储的也是唯一的!
03.那么怎么知道 map中的key是唯一的呢? 看hashMap的put() String的底层 是 char类型的数组!
怎么比较两个值是否一致? 把char数组中的每一个元素都比较,全相等 才相等! 所以hashMap在添加数据的时候
01.先进行hash运算
02.把计算的值当成数组中的下标
03.判断下标指向的数组元素是否为空,如果为空 直接 添加数据
04.如果不为空
依次查询entry中的所有元素
05.判断key是否相等
001.e.hash == hash
002.(k = e.key) == key || key.equals(k)
如果相等 直接覆盖
不相等 通过next的变量 将值 新增到entry! HashSet 和 TreeSet的区别 01. HashSet底层是哈希表实现的!
TreeSet底层是二叉树实现的!
02. HashSet存放的数据是无序的!
TreeSet存放的数据是有序的!
03. HashSet可以存放 null!但是只能是一个null!
TreeSet不可以存放null!
04. HashSet底层是由HashMap实现!
TreeSet底层是由TreeMap实现!
05. HashSet是线程不安全的! 单线程是安全!
TreeSet是线程安全的! */ } }

set

import java.util.HashSet;
import java.util.Set; import org.junit.Test; public class StringTest { public static void main(String[] args) { Set set = new HashSet();
set.add("1");
set.add(new String("1"));
set.add(new String("1"));
System.out.println(set.size()); // 疑问? 为什么 两次new 确是一样的
String a = new String("1");
String b = new String("1");
String c = "1";
System.out.println(a == b);
System.out.println(a == c);
// 内容相同的String对象 hashCode是一致的!
System.out.println(a.hashCode() == b.hashCode());
System.out.println(a.hashCode() == c.hashCode());
} @Test
public void test1() {
String a = new String("1");
/**
* 01.首先在栈中开辟空间存储a
* 02.去常量池中查询有没有 字符串1 没有就在常量池中创建字符串1
* 03.再去堆中创建一个字符串1
* 04.a指向堆中的字符串1
*/
String b = "1";
/**
* 01.首先在栈中开辟空间存储b
* 02.去常量池中查询有没有 字符串1 有
* 03.b指向常量池中的字符串1
*/
System.out.println(a == b); // false
} @Test
public void test2() {
String a = "abc";
String b = "abc";
System.out.println(a == b); // true
System.out.println(a == "abc"); // true
} @Test
public void test3() {
String a = "abc";
String b = "a";
String c = "bc";
System.out.println(a == ("a" + "bc")); // true
/**
* b 和 c 都是变量!!!!!!
* 在运行期间可以改变的量!
*/
System.out.println(a == (b + c)); // false
} @Test
public void test4() {
String a = "abc";
final String b = "a";
final String c = "bc";
System.out.println(a == ("a" + "bc")); // true
/**
* 在编译期间因为b 和 c 都是常量
* 所以就把b+c="abc"
*/
System.out.println(a == (b + c)); // true
}
}

HashSet

6.Map

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import org.apache.log4j.Logger;
import org.junit.Test; import cn.bdqn.listtest.News; public class MapTest { public static void main(String[] args) { /**
* Map: 是一个key value 键值对的集合!
* key是唯一的!
*
* 存放值:
* put(key,value)
*
* 取值
* get(key) 根据key获取value
*/ Map map = new HashMap();
map.put(1, "haha1");
map.put("1", "haha2");
map.put(new String("1"), "haha3");
System.out.println(map.size());
} @Test
public void test1() {
Map map = new HashMap();
map.put("news1", new News(1, "新闻标题1"));
map.put("news2", new News(2, "新闻标题2"));
map.put("news3", new News(3, "新闻标题3"));
/**
* 我们想获取value的值 只能通过key
* key是一个集合 就是set
*/
Set keySet = map.keySet();
for (Object o : keySet) {
System.out.println(o); // key
}
/**
* 获取所有value的集合
*/
Collection values = map.values();
for (Object o : values) {
System.out.println(o); // value
} System.out.println("****************************"); // 直接使用一个循环 获取value
for (Object key : keySet) {
News news = (News) map.get(key); // 根据key获取value
System.out.println(news);
}
System.out.println("****************************");
Iterator it = keySet.iterator();
while (it.hasNext()) {
News news = (News) map.get(it.next());
System.out.println(news);
} System.out.println("************ EntrySet()****************"); /**
* 强烈推荐使用 EntrySet()
* 可以在获取key的同时获取value!不需要两次查询
*/
Iterator it1 = map.entrySet().iterator();
while (it1.hasNext()) {
Entry entry = (Entry) it1.next();
System.out.println("map中的key:" + entry.getKey());
System.out.println("map中的value:" + entry.getValue());
}
} Logger log = Logger.getLogger(MapTest.class); @Test
public void test2() {
Map map = new HashMap();
for (int i = 1; i <= 200000; i++) {
map.put(i, "" + i);
}
System.out.println("map的大小:" + map.size()); // 获取当前的毫秒数 从1970年1月1日到现在的毫秒
long start = System.currentTimeMillis();
Set keySet = map.keySet();
for (Object key : keySet) {
System.out.println(map.get(key));
}
long end = System.currentTimeMillis();
log.debug("使用for循环的用时:" + (end - start)); start = System.currentTimeMillis();
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Entry entry = (Entry) iterator.next();
System.out.println(entry.getValue());
}
end = System.currentTimeMillis();
log.debug("使用Iterator循环的用时:" + (end - start));
} /***
*
* HashMap 和 HashTable 的区别
* 01.HashMap 线程不安全 但是性能高
* HashTable 线程 安全 但是性能低
* 02.HashMap 底层是哈希表实现的,每一个元素一个key -value键值对!
* key和value都可以为null!
* HashTable的key和value都不可以为null!
* 03.历史版本不同
* HashMap 1.2
* HashTable 1.0
*/
}

MapTest

7.泛型

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import org.junit.Test; import cn.bdqn.listtest.News; public class MyTest { @Test
public void test01() {
ArrayList list = new ArrayList();
// list中可以存放什么类型! Object 所有类型
list.add(1);
list.add("1");
list.add(new Date());
/**
* 我们怎么去遍历这些类型的数据
* 01.集合中的数据不是相同类型
* 02.不能按照一种方式去遍历
*/ Set set = new HashSet();
set.add(1);
set.add("1");
set.add(new Date()); Map map = new HashMap();
map.put(1, "1");
map.put("1", "haha");
map.put("2", new Date()); /**
* 上面三个 集合
* 01.因为我们没有在创建集合的同时 规定集合中可以存放什么类型的数据
* 02.所以集合中可以存放Object类型的数据
* 03.导致后续操作很麻烦
* 04.如果我们想获取集合中的某个元素,需要使用get()
* 05.但是get()返回值是 object类型
* 06.需要向下转型,转换成指定的类型,之后才能操作!
*
*
* 有没有一种方式,
* 01.可以在创建集合的时候,规定集合中只能存放什么类型
* 02.能不能在get()不进行向下转型!!!
*
* 能!
* 使用泛型!
* 泛型集合: 创建集合的时候,规定集合中存放数据的类型!
*
*/ } /**
* 使用泛型集合 方便+安全
* <> 就是集合中指定的元素类型!
*
* 泛型集合中 不允许 存放基本数据类型的元素!
* 如果想存放基本数据类型!
* 必须使用基本数据类型对应的 包装类
*
* java中有8种基本数据类型,使用ctrl+鼠标左键 点不进去! 说明不是类
*
* 那就有8个对应的包装类!
* byte Byte
* short Short
* int Integer
* long Long
* float Float
* double Double
*
* boolean Boolean
* char Character
*
*/
@Test
public void test02() {
ArrayList<String> list = new ArrayList<String>();
// 说明list集合中只能存放String类型的数据
// list.add(new Date()); 编译报错
ArrayList<News> list2 = new ArrayList<News>();
// list2集合中 只能存放 News 对象!
ArrayList<Double> list3 = new ArrayList<Double>();
list3.add(2.0); double a = 2;
// Double b = 2; 编译报错
} @Test
public void test03() {
/**
* 创建了一个map泛型集合!
* 集合的key只能是String类型
* value只能是News类型!
*
* map.put(1,"1"); 错误
* map.put("1","1"); 错误
* map.put("1",new News());
*/
Map<String, News> map = new HashMap<>();
News news1 = new News(1, "新闻1");
News news2 = new News(2, "新闻2");
News news3 = new News(3, "新闻3");
map.put("a", news1);
map.put("b", news2);
map.put("c", news3); // 遍历出来所有的新闻信息
Iterator<Entry<String, News>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, News> entry = iterator.next();
// System.out.println(entry.getKey()); 获取所有的key
News news = entry.getValue(); // 获取所有的value
System.out.println(news);
} }
}

泛型

java高级⑴的更多相关文章

  1. [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html   谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...

  2. paip.java 架构师之路以及java高级技术

    paip.java 架构师之路以及java高级技术 1.    Annotation 设计模式... 概念满天飞.ORM,IOC,AOP. Validator lambda4j memcache. 对 ...

  3. paip。java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型

    paip.java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型 作者Attilax 艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http ...

  4. Java高级之线程同步

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 关于实现多线程的意义,"从业四年看并发"一文已经讲述,而本篇主要讲一下常用的设计 ...

  5. Java高级之类结构的认识

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! Java体系包括,各种版本的虚拟机,可执行文件,各种第三方类库,Java API类库,Java语言 ...

  6. Java高级软件工程师面试考纲(转)

    如果要应聘高级开发工程师职务,仅仅懂得Java的基础知识是远远不够的,还必须懂得常用数据结构.算法.网络.操作系统等知识.因此本文不会讲解具体的技术,笔者综合自己应聘各大公司的经历,整理了一份大公司对 ...

  7. Java高级软件工程师面试考纲

    如果要应聘高级开发工程师职务,仅仅懂得Java的基础知识是远远不够的,还必须懂得常用数据结构.算法.网络.操作系统等知识.因此本文不会讲解具体的技术,笔者综合自己应聘各大公司的经历,整理了一份大公司对 ...

  8. 黑马程序员——Java高级应用(一)

    ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS ...

  9. 2017最新技术java高级架构、千万高并发、分布式集群、架构师入门到精通视频教程

    * { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩展. ...

  10. 这月薪过万的Java高级学习资料,难得一遇的干货,不下载真可惜了!

    大家有没有想我呢 不管你们想不想我 我挺想你们的 通过昨天我不断的 死气白咧各种说好话 最终 要到了Java学科的Java集合学习资料 里面包含视频+资料+源码 堂兄也有一个愿望 希望你们月薪过万后 ...

随机推荐

  1. vue.js环境配置步骤及npm run dev报错解决方案

    安装完成后,使用npm run dev 运行,成功后,就可以在浏览器中看到vue的欢迎画面了 最后一步可能报错,我就遇到这样的问题了, 个人问题仅供参考: ERROR Failed to compil ...

  2. ip网关配置

    流量查看watch more /proc/net/devip子网查询https://www.sojson.com/convert/subnetmask.htmlhttp://ip.gchao.cn/ ...

  3. selenium+Page Objects(第二话)

    前面介绍了什么是po模式,并且简单分析了一下使用po模式编写脚本的思路,接下来开始正式编写 1.先编写一个页面基类BasePage.py,里面封装每个页面常用的一些方法 # coding: utf-8 ...

  4. HTML 第十二章总结

    HTML5 markup 前言 在这一章中,讲解了新的 HTML5 的一些 markup,并且对其中的<video>进行了很详细的讲解. New HTML5 elements 列表如下: ...

  5. [LintCode] Binary Tree Level Order Traversal(二叉树的层次遍历)

    描述 给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问) 样例 给一棵二叉树 {3,9,20,#,#,15,7} : 3 / \ 9 20 / \ 15 7 返回他的分层遍历结果: [ [3] ...

  6. unitest discover 模板实例

    说明:测试用例和主函数分开存放

  7. 5月30---6月2 DedeCMS以及动态仿站

    什么是DedeCMS 织梦内容管理系统(DedeCMS),是一个集内容发布.编辑.管理检索等于一体的网站管理系统(Web CMS),他拥有国外CMS众多特点之外,还结合中国用户的需要,对内容管理系统概 ...

  8. hadoop集群添加新节点

    0.说明 Hadoop集群已经运行正常,现在新买了一些机子,要加入到集群里面增加新的节点.以下就是增加的过程. 1.配置运行环境 安装与master和其他slave相同的java环境,jdk版本要相同 ...

  9. vue中使用transition标签底部导航闪烁问题

    <transition :name="transitionName" :duration="{ enter: 500, leave: 0 }" > ...

  10. leetcode-algorithms-35 Search Insert Position

    leetcode-algorithms-35 Search Insert Position Given a sorted array and a target value, return the in ...