1.泛型(jdk1.5以后出现)

https://www.cnblogs.com/lwbqqyumidi/p/3837629.html#!comments

1)为什么要用泛型?

  限制集合,让它只能存储某种类型的元素,如果不限制,集合(默认Object类型)中想存什么就存什么,这样在取元素的时候就会面临大量强制类型转换,这就很可能出现转换异常,为了解决这个问题,jdk1.5以后就出现泛型

  当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。因此,当我们取出集合元素时需要人为的强制类型转化到具体的目标类型,这就很容易很容易出现“java.lang.ClassCastException”异常

(2)泛型概述

  泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变化量话参数,此时类型也定义成参数形式(可称之为类型形参),然后在使用/调用时传入具体的类型(类型实参),一般用"<E>"表示。泛型只在编译时有效,在生成的.class文件中,会把泛型擦除掉。

(3)泛型定义

a  定义在类上

 若类在定义时没有加泛型时,则在创建对象时,不能使用泛型,如下图

此时Box定义时加上泛型,如下

public class GenericDemo {
public static void main(String[] args) {
Box<Integer> box = new Box<>(2); //右边的尖括号内不需要写具体的可类型,jdk.7以后会根据左边自动识别出类型是什么
}
}
class Box<T>{
T t; // T的类型是什么由创建对象时确定,如此处T就是Integer类型
public Box(T t) {
this.t = t;
}
public T getT() {
return t;
}
}

注意,类在创建对象时,不加泛型,默认是Object类型

b  定义在方法上(不常用)

用法:方法的逻辑相同,只是数据类型不同,这个时候使用反省方法,泛型写在返回值之前,以Collections中sort方法的源码为例

public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}

用了泛型后,sort方法中List中的参数类型就可以不同

public class GenericDemo {
public static void main(String[] args) {
String str = cast("aaa");
}
public static<E> E cast(Object o) {
return (E)o;// 强制类型转换,向下转型
}
}

c. 泛型定义在接口上

interface A<E>{
public void test(E e);
}
// 如果实现的接口没有指定具体的类型,则子类必须泛型下去
class B<E> implements A<E>{
public void test(E e) { }
}
// 如果实现的接口给定了具体的类型,子类中用到泛型的地方都必须使用该类型
class C implements A<String>{ @Override
public void test(String e) { }
}

 (4)泛型通配符

泛型通配符:

    泛型通配符<?>

        任意类型,如果没有明确,那么就是Object以及任意的java类了

      ?extends E

        向下限定,E及其子类

      ?super E

        向上限定,E及其父类

  注意:泛型的通配值只能用在=的左边或者是参数列表上

public class GenericDemo2 {
public static void main(String[] args) {
Collection<?> c1 = new ArrayList<Animal>();
Collection<?> c2 = new ArrayList<Dog>();
Collection<?> c3 = new ArrayList<Cat>();
Collection<?> c4 = new ArrayList<Object>();
Collection<? extends Animal> c5 = new ArrayList<Animal>();
Collection<? extends Animal> c6 = new ArrayList<Dog>();
Collection<? extends Animal> c7 = new ArrayList<Cat>();
//Collection<? extends Animal> c8 = new ArrayList<Object>();报错
Collection<? super Animal> c9 = new ArrayList<Animal>();
// Collection<? super Animal> c10 = new ArrayList<Dog>();报错
// Collection<? super Animal> c11 = new ArrayList<Cat>();报错
Collection<? super Animal> c12 = new ArrayList<Object>();
}
} class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

2. foreach(增强for循环)

  简化数组和Collection集合的遍历

  格式:

     for(元素数据类型 元素名 :数组或者Collection集合){对元素进行你自己的操作}

  好处:简化遍历

  注意事项:增强for的目标要判断是否为null

数组遍历

public class ForeachClass {
public static void main(String[] args) {
String[] str = new String[] {"哈","哈"};//当此处的数组为null时就会报java.lang.NullPointerException错误,所以要加验证,如下集合例子
for(String a:str) {
System.out.println(a);
}
}
}

集合的遍历

public class ForeachClass {
public static void main(String[] args) {
List<Person> ps = new ArrayList<>();
ps.add(new Person("张三",27));
ps.add(new Person("张一",17));
ps.add(new Person("李四",37));
ps.add(new Person("老王",67));
ps.add(new Person("小红",25));
if(ps!=null && ps.size()>0) {
for(Person p:ps) {
System.out.println(p);
}
}
}
}
class Person{
String name;
int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
} }

3. 可变参数

  定义方法的时候不知道该定义多少个参数

格式:

  修饰符  返回值类型  方法名(数据类型···  变量名)

注意:

  这里的变量其实是一个数组

  如果一个方法有可变参数,并且有多个参数,那么,可变参数必须是最后一个(若放前面的话,不能确定哪个参数时不可变参数)

案例

public class ChangeableParamDemo {
public static void main(String[] args) {
System.out.println(getSum(1,2,33));
}
public static int getSum(int b, int...a) { //此变量a为数组
int sum = 0;
System.out.println(b);
for(int i=0;i<a.length;i++) {
sum += a[i];
}
return sum;
}
}
// 运行结果:
1
35

4. 数组和集合间的转换

  1.集合转数组;

     toArray(collection):   得到   Object[ ]

  2.数组转集合:

案例

public class ArrayAndCollection {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("老王");
list.add("小明");
//1 集合转数组
Object[] o = list.toArray();
System.out.println(o);
//2 数组转集合
String[] str = {"1","2"};
List<String> list1 = Arrays.asList(str);
System.out.println(list1 instanceof List);//true
}
}

注意,使用alist得到的集合是不能进行add和remove操作的(只能是可读的集合,

原因:此处asList返回的是一个ArrayList对象,但这个ArrayList是Arrays里面的内部类,这个类中没有实现增加和删除的方法  

如果非要操作,需要创建一个新的集合,把它传入到构造方法中,如下

Integer[] arr = {1,2};
List<Integer> list1 = Arrays.asList(arr);
List<Integer> list2 = new ArrayList<>(list1);
list2.add(100);
System.out.println(list2);//[1, 2, 100]

5.Set

(1)

特点:Set的元素时无序的(不能使用索引操作元素),元素不可重复

collection:

   List():  有序的,元素可重复

         ArrayList

       LinkedList:特有方法(增删,获取集合首个和最后一个元素)

     Set(): 无序的(不能使用索引操作元素),元素不能重复

      HashSet:无法保证存入和取出的顺序

      LinkedHashSet:可以保证存入和取出的顺序(链表实现)

      TreeSet:有序的(可以对元素排序)

不可重复性的原理:

  是由hashCode和equals方法保证的

  存放元素的时候,先求出元素的hashCode,如果集合中没有这样的hashCode值,说明该元素在集合中不存在,可以存;有这样的hashCode,再比较equals:如果为true,集合中已经存在噶元素,则不存,如果为false,则可以存。

案例

public class SetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("小猫警长");
set.add("黑猫警长");
set.add("白猫警长");
set.add("花猫警长");
set.add("白猫警长");
set.add("花猫警长");
set.add("黑猫警长");
set.add("红猫警长");
System.out.println(set);
}
}
// 运行结果:[黑猫警长, 红猫警长, 白猫警长, 花猫警长, 小猫警长]

可见存入的顺序并不有序,若想有序可以使用LinkedHashSet创建对象

(2)Set的遍历(三种方法)

第一种:数组

public class SetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("小猫警长");
set.add("黑猫警长");
set.add("白猫警长");
set.add("花猫警长");
set.add("红猫警长");
Object[] array = set.toArray();
for(Object s:array) {
System.out.println(s);
}
}
}

第二种:迭代器

Iterator<String> it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}

第三种(增强for循环)

for(String str :set) {
System.out.println(str);
}

练习

1. 使用LinkedHashSet填写一个程序,获取10个1至20的随机数,要求随机数不能重复

public class TenNum {
public static void main(String[] args) {
Set<Integer> set = new LinkedHashSet<>();
Random r = new Random();
while(set.size()<10) {
int num = r.nextInt(20)+1;
set.add(num);
}
System.out.println(set);
}
}

2. 使用集合去重

public class SetQuChong {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(1);
list.add(2);
list.add(2);
List<Integer> list1 = distinct(list);
System.out.println(list1);
}
public static List<Integer> distinct(List<Integer> list){
Set<Integer> set = new HashSet<>();
set.addAll(list);
list.clear();
list.addAll(set);
return list;
}
}
// 运行结果:[1,2]

6. Map

6.1 概述

  双列集合的跟接口;将键映射到值的对象;一个映射不能包含重复的键,每个键最多只能映射到一个值。

Map接口和Collection接口的不同:

  Map是双列的,Colection是单列的

  Map的键唯一(值可以不唯一),Collection的子体系只有Set是唯一的

6.2 Map接口的成员方法

V put(K key,V value) 添加元素(返回值是Key上一次对应的Value)
V remove(Object key) 移除key对应的键值对(返回值是value)
void clear() 清空map
boolean containsKey(Object key) 是否包含key
boolean containsValue(Object value) 是否包含value
boolean isEmpty() 是否为空
int size() 键值对的个数

V put(K key,V value) 添加元素(返回值是Key上一次对应的Value)

public class MapDemo {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
String re = map.put("a","啊,五环,你比四环多一环");
System.out.println(re);
String re1 = map.put("a","啊,四环,你比五环少一环");
System.out.println(re1);
}
}
//运行结果:
null
啊,五环,你比四环多一环

由结果可知,put的返回值为当次被覆盖的内容(第一次打印的结果为null,相当于第一次添加值将null覆盖)

V remove(Object key) 移除key对应的键值对(返回值是被移除键值对中的value)

System.out.println(map);//{a=啊,四环,你比五环少一环}
String re2 = map.remove("a");
System.out.println(re2);//啊,四环,你比五环少一环

get(key) 方法(可用于遍历),返回值为key所对应的值

System.out.println(map);//{a=啊,四环,你比五环少一环}
String re3 = map.get("a");
System.out.println(re3);//啊,四环,你比五环少一环

6.3 Hashmap的遍历

第一种  keySet  获取所有key

public class MapDemo {
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(1, "小明");
map.put(2, "小红");
map.put(3, "小王");
map.put(4, "小李");
Set<Integer> keySet = map.keySet();
for(Integer key:keySet) {
System.out.println("key:"+key+",value:"+map.get(key));
}
}
}

第二种  entrySet(获取键值对)

Set<Entry<Integer, String>> entrySet = map.entrySet();
for (Entry<Integer, String> entry:entrySet) {
  System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
}

使用迭代器实现:


Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while(it.hasNext()) {
System.out.println(it.next());
System.out.println("key:"+next.getKey()+",value:"+next.getValue());
}

第三种  values:只能得到所有的value

Collection<String> values = map.values();
for (String v :values) {
System.out.println(v);
}

6.4 HashMap的实现原理

使用散列表(由数组和链表组成)或哈希表来实现的(效率高)

数组+链表:元素是链表的数组(主体是数组)

练习:统计一个字符串中各个字符出现的次数

public class StrTimes {
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.nextLine();
// 创建map,用来存储数据
Map<Character, Integer> map = new HashMap<>();
// 遍历获取每一个字符
for(int i=0;i<str.length();i++) {
char ch = str.charAt(i);
//用ch做key去map中查询是否有值
Integer value = map.get(ch);
if(value == null) {
map.put(ch, 1);
}else {
value++;
map.put(ch,value);
}
}
Set<Character> keySet = map.keySet();
for(Character c:keySet) {
System.out.println("字符"+c+"的次数:"+map.get(c));
}
}
}

零基础学习java------day14-----泛型,foreach,可变参数,数组和集合间的转换,Set,Map,的更多相关文章

  1. 音乐出身的妹纸,零基础学习JAVA靠谱么

    问:表示音乐出身的妹纸一枚  某一天突然觉得身边认识的是一群程序员   突然想 要不要也去试试... 众好友都觉得我该去做个老师,可是我怕我会误人子弟,祸害祖国下一代..... 要不要 要不要 学Ja ...

  2. 总结了零基础学习Java编程语言的几个基础知识要点

    很多Java编程初学者在刚接触Java语言程序的时候,不知道该学习掌握哪些必要的基础知识.本文总结了零基础学习Java编程语言的几个基础知识要点. 1先了解什么是Java的四个方面   初学者先弄清这 ...

  3. 中国MOOC_零基础学Java语言_第5周 数组_1多项式加法

    第5周编程题 查看帮助 返回   第5周编程题 依照学术诚信条款,我保证此作业是本人独立完成的. 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业截 ...

  4. 零基础学Java(13)方法参数

    前言 首先回顾一下在程序设计语言中关于如何将参数传递给方法的一些专业术语.按值调用表示方法接收的是调用者提供的值.而按引调用表示方法接收的是调用者提供的变量地址.方法可以修改按引用传递的变量的值,而不 ...

  5. 中国MOOC_零基础学Java语言_第5周 数组

    第5周 数组 5.1 数组 5.2 数组计算 public class Main { public static void main(String[] args) { for (int i = 1; ...

  6. Effective Java 第三版——32.合理地结合泛型和可变参数

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  7. 零基础学Java第四节(字符串相关类)

    本篇文章是<零基础学Java>专栏的第四篇文章,文章采用通俗易懂的文字.图示及代码实战,从零基础开始带大家走上高薪之路! String 本文章首发于公众号[编程攻略] 在Java中,我们经 ...

  8. 如何从零基础学习VR

    转载请声明转载地址:http://www.cnblogs.com/Rodolfo/,违者必究. 近期很多搞技术的朋友问我,如何步入VR的圈子?如何从零基础系统性的学习VR技术? 本人将于2017年1月 ...

  9. 【零基础学习iOS开发】【转载】

    原文地址:http://www.cnblogs.com/mjios/archive/2013/04/24/3039357.html 本文目录 一.什么是iOS 二.主流手机操作系统 三.什么是iOS开 ...

随机推荐

  1. Pod 生命周期和重启策略

    Pod 在整个生命周期中被系统定义为各种状态,熟悉 Pod 的各种状态对于理解如何设置 Pod 的调度策略.重启策略是很有必要的. Pod 的状态 状态值 描述 Pending API Server ...

  2. Webshell 一句话木马

    Webshell介绍 什么是 WebShell webshell就是以asp.php.jsp或者cgj等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门 由于 webshell其大多是 ...

  3. airflow redis sentinel

    获取master name subscribe __sentinel__:hello mysql plugin table not found mysqld --initialize-insecure ...

  4. MyBatis 中为什么不建议使用 where 1=1?

    最近接手了一个老项目,"愉悦的心情"自然无以言表,做开发的朋友都懂,这里就不多说了,都是泪... ​ 接手老项目,自然是要先熟悉一下业务代码,然而在翻阅 mapper 文件时,发现 ...

  5. 【Sass/SCSS】预加载器中的“轩辕剑”

    [Sass/SCSS]预加载器中的"轩辕剑" 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 随着前端 ...

  6. SpringCloud升级之路2020.0.x版-37. 实现异步的客户端封装配置管理的意义与设计

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 为何需要封装异步 HTTP 客户端 WebClient 对于同步的请求,我们使用 spri ...

  7. C#中指针的使用(转)

    在C#中,有时候希望通过指针来操作内存,这样可以提高效率.我们可以用unsafe关键字修饰含有指针操作的程序段,如下所示: class Program {   static int Main(stri ...

  8. 快速从零开始整合SSM,小白包会(1)

    整合SSM,关键就是几个xml的配置. 准备: 1.   Idea(配置好tomcat,可以安装插件freeMybatis,提高效率,安装插件不难,百度经验就有) 2.   下载好数据库MySql,以 ...

  9. 论文翻译:2020_WaveCRN: An efficient convolutional recurrent neural network for end-to-end speech enhancement

    论文地址:用于端到端语音增强的卷积递归神经网络 论文代码:https://github.com/aleXiehta/WaveCRN 引用格式:Hsieh T A, Wang H M, Lu X, et ...

  10. CF1463E Plan of Lectures

    考虑我们两种操作: 我们把第一种操作在\(x\to y\)连一条权为-1的边. 第二种操作\(x\to y\)连-1,\(y\to x\)连1的边. 当无法操作则是环里有负环. 否则我们把第二种操作涉 ...