java可变参数 map_零基础学习java------day14-----泛型,foreach,可变参数,数组和集合间的转换,Set,Map,...

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

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

(1)为什么要用泛型?

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

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

(2)泛型概述

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

(3)泛型定义

a  定义在类上

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

fa19832d70a40f4f306fa9b2d1554c7a.png

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

public classGenericDemo {public static voidmain(String[] args) {

Box box = new Box<>(2); //右边的尖括号内不需要写具体的可类型,jdk.7以后会根据左边自动识别出类型是什么

}

}class Box{

T t; // T的类型是什么由创建对象时确定,如此处T就是Integer类型publicBox(T t) {this.t =t;

}publicT getT() {returnt;

}

}

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

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

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

public static > void sort(Listlist) {

list.sort(null);

}

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

public classGenericDemo {public static voidmain(String[] args) {

String str= cast("aaa");

}public staticE cast(Object o) {return(E)o;// 强制类型转换,向下转型

}

}

c. 泛型定义在接口上

interface A{public voidtest(E e);

}//如果实现的接口没有指定具体的类型,则子类必须泛型下去

class B implements A{public voidtest(E e) {

}

}//如果实现的接口给定了具体的类型,子类中用到泛型的地方都必须使用该类型

class C implements A{

@Overridepublic voidtest(String e) {

}

}

(4)泛型通配符

泛型通配符:

泛型通配符>

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

?extends E

向下限定,E及其子类

?super E

向上限定,E及其父类

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

public classGenericDemo2 {public static voidmain(String[] args) {

Collection> c1 = new ArrayList();

Collection> c2 = new ArrayList();

Collection> c3 = new ArrayList();

Collection> c4 = new ArrayList();

Collection extends Animal> c5 = new ArrayList();

Collection extends Animal> c6 = new ArrayList();

Collection extends Animal> c7 = new ArrayList();//Collection extends Animal> c8 = new ArrayList();报错

Collection super Animal> c9 = new ArrayList();//Collection super Animal> c10 = new ArrayList();报错//Collection super Animal> c11 = new ArrayList();报错

Collection super Animal> c12 = new ArrayList();

}

}classAnimal {}classDog extends Animal {}class Cat extends Animal {}

2. foreach(增强for循环)

简化数组和Collection集合的遍历

格式:

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

好处:简化遍历

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

数组遍历

public classForeachClass {public static voidmain(String[] args) {

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

System.out.println(a);

}

}

}

集合的遍历

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classForeachClass {public static voidmain(String[] args) {

List 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);

}

}

}

}classPerson{

String name;intage;public Person(String name, intage) {

super();this.name =name;this.age =age;

}

@OverridepublicString toString() {return "Person [name=" + name + ", age=" + age + "]";

}

}

View Code

3. 可变参数

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

格式:

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

注意:

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

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

案例

public classChangeableParamDemo {public static voidmain(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

sum+=a[i];

}returnsum;

}

}

// 运行结果:

1

35

4. 数组和集合间的转换

1.集合转数组;

toArray(collection):   得到   Object[ ]

2.数组转集合:

案例

public classArrayAndCollection {public static voidmain(String[] args) {

List list = new ArrayList<>();

list.add("老王");

list.add("小明");//1 集合转数组

Object[] o =list.toArray();

System.out.println(o);//2 数组转集合

String[] str = {"1","2"};

List list1 =Arrays.asList(str);

System.out.println(list1 instanceof List);//true

}

}

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

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

46b8b1a35654291295b83bb9f9e47459.png

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

Integer[] arr = {1,2};

List list1 =Arrays.asList(arr);

List 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,则可以存。

案例

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classSetDemo {public static voidmain(String[] args) {

Set set = new HashSet<>();set.add("小猫警长");set.add("黑猫警长");set.add("白猫警长");set.add("花猫警长");set.add("白猫警长");set.add("花猫警长");set.add("黑猫警长");set.add("红猫警长");

System.out.println(set);

}

}//运行结果:[黑猫警长, 红猫警长, 白猫警长, 花猫警长, 小猫警长]

View Code

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

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

第一种:数组

public classSetDemo {public static voidmain(String[] args) {

Set 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 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 classTenNum {public static voidmain(String[] args) {

Set set = new LinkedHashSet<>();

Random r= newRandom();while(set.size()<10) {int num = r.nextInt(20)+1;set.add(num);

}

System.out.println(set);

}

}

2. 使用集合去重

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classSetQuChong {public static voidmain(String[] args) {

List list = new ArrayList<>();

list.add(1);

list.add(1);

list.add(2);

list.add(2);

List list1 =distinct(list);

System.out.println(list1);

}public static List distinct(Listlist){

Set set = new HashSet<>();set.addAll(list);

list.clear();

list.addAll(set);returnlist;

}

}//运行结果:[1,2]

View Code

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)voidclear() 清空map

boolean containsKey(Object key) 是否包含key

boolean containsValue(Object value) 是否包含value

boolean isEmpty() 是否为空int size() 键值对的个数

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

public classMapDemo {public static voidmain(String[] args) {

Map 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 classMapDemo {public static voidmain(String[] args) {

Map map = new HashMap<>();

map.put(1, "小明");

map.put(2, "小红");

map.put(3, "小王");

map.put(4, "小李");

Set keySet =map.keySet();for(Integer key:keySet) {

System.out.println("key:"+key+",value:"+map.get(key));

}

}

}

第二种  entrySet(获取键值对)

Set> entrySet =map.entrySet();for (Entryentry:entrySet) {

System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());

}

使用迭代器实现:

Iterator> it = map.entrySet().iterator();

while(it.hasNext()) {

System.out.println(it.next());

System.out.println("key:"+next.getKey()+",value:"+next.getValue());

}

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

Collection values =map.values();for(String v :values) {

System.out.println(v);

}

6.4 HashMap的实现原理

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

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

b99fa488ecced50c118507ea037c71d9.png

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

public classStrTimes {public static voidmain(String[] args) {

Scanner sc= new Scanner(System.in);

System.out.println("请输入一个字符串");

String str=sc.nextLine();//创建map,用来存储数据

Map map = new HashMap<>();//遍历获取每一个字符

for(int i=0;i

Integer value = map.get(ch);if(value == null) {

map.put(ch,1);

}else{

value++;

map.put(ch,value);

}

}

Set keySet =map.keySet();for(Character c:keySet) {

System.out.println("字符"+c+"的次数:"+map.get(c));

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值