引言:
在实际项目开发中或者一些算法面试题目中经常需要用到Java中这三种类型的相互转换,比如对于一个整型数组中寻找一个整数与所给的一个整数值相同,正常情况下第一反应会想到用for循环直接遍历这个数组就可以实现,不过这种情况下时间复杂度将会是O(n),空间复杂度是O(1)。如果再多加几个条件还使用多层for循环嵌套的话也可以实现,不过时间复杂度将会以指数级增长。我们可以说多层for循环嵌套可以实现功能,但就执行时间来说,它绝不会是一个好的解决方法。那么如何降低时间复杂度呢,这个时候我们可以考虑一下将这个整型数组转换为一个Map,因为Map是以key,value键值对形式存储,value允许重复,但是key不允许重复。使用Map中map.containsKey()方法可以轻松实现对于key是否存在一个值的查找,此种方法时间复杂度为O(1),空间复杂度为O(n),其中 n 是数组中的元素数量,主要为哈希表的开销。这就降低了方法的执行时间,算是一种算法上的优化。
补充:
一个好的算法要求正确性、可读性、健壮性、时间效率高而且空间使用率低、简单性。
算法的复杂度分为时间复杂度和空间复杂度。
时间复杂度:
时间复杂度实际上是一个函数,代表基本操作重复执行的次数,进而分析函数虽变量的变化来确定数量级,数量级用O表示,如O(1),O(n),O(n^2)等。
空间复杂度:
是对一个算法在运行过程中临时占用存储空间的度量,一个算法在计算机存储器上所占用的存储空间包括存储算法本身所占用的空间,算数和输入输出所占用的存储空间以及临时占用存储空间三个部分,算法的输入输出数据所占用的存储空间是由待解决的问题来决定的,通过参数表由调用函数而来,它随本算法的不同而改变,存储算法本身所占用的存储空间有算法的书写长短成正比。算法在运行过程中占用的临时空间由不同的算法决定。
时间复杂度与空间复杂度没有必然联系,但是也有以空间换时间或时间换空间,现今项目中一般要求效率,大部分需要降低执行时间即降低时间复杂度,以空间换时间来提高效率。不过在这两者之间取舍需要具体问题具体分析。
正文:
Array转List:
有两种方法可以将array转为list,一种是使用Arrays.asList()方法直接转换,不过此种方法的list长度固定,无法进行添加删除操作。另一种是使用for循环遍历数组元素逐个添加进一个空的list中。
/**
* 方法一:使用Arrays.asList()方法将数组转为list,不过此种方法有限制,返回的对象是Arrays的内部类
* 对于转换后的list操作仍然反映在原数组上,因此这个list是定长的,无法使用list的add()喝remove()方法
*/
public static void array_list(String[] array){
List<String> list = Arrays.asList(array);
System.out.println("数组转List 的第一种方法:"+list);
// list.remove("李四");
// list.add("刘六");
// System.out.println(“修改后:”list);
}
/**
* 方法二:正常情况下array转换为list,使用for循环将数组中的元素逐个添加到一个空的list中
*/
public static void array_list2(String[] array){
List<String> list = new ArrayList<>();
for (int i=0;i<array.length;i++){
list.add(array[i]);
}
System.out.println("数组转List 的第二种方法:"+list);
list.remove("李四");
list.add("刘六");
System.out.println("修改后:"+list);
}
List转为Array:
使用list.toArray()将List直接转换为Array
//List转Array
public static void list_array(List<String> list){
String[] array =list.toArray(new String[list.size()]);
System.out.println("List转数组:"+array);
}
Array转Map:
当数组是一维数组时,奇数位是key键,偶数位是value值。数组有奇数个元素时,舍弃最后一个元素。
//Array转Map
/**
*一维数组时,奇数位为key键,偶数位为value,如果有奇数个元素,最后一个舍掉
*/
public static void array_map(String[] array) {
Map map = MapUtils.putAll(new HashMap(),array);
System.out.println("数组转Map:"+map);
}
当数组是二维数组时,可以看作两个一维数组,使用ArrayUtils.toMap()方法转换
/**
* 二维数组时,当成两个一维数组,使用ArrayUtils.toMap()方法转换
*/
public static void array_map2(String[][] array2){
Map map2 = ArrayUtils.toMap(array2);
map2.put("南昌","江西");
System.out.println("二维数组转Map:"+map2);
}
Map转Array:
Map只需要value值时,将Map的values转为一维数组:
使用map.values().toArray()方法将map转为object类型的数组,特定类型数组需要再次转换。
其中Stream API和方法引用是Java8的新特性,可以参考以下几篇文章:
【java8新特性】Stream API详解 、 【java8新特性】方法引用 、
//Map转Array
/**
*Map只需要value值时,将Map的values转为一维数组
*使用map.values().toArray()将map转为object数组,如果想要转为特定类型的数组需要再进一步转换
*/
public static void map_array(Map<Integer,String> map){
Object[] obj = map.values().toArray();
/**
* 第一种,使用Arrays.copyOf()方法将原数组内的元素拷贝到一个新的String类型的数组
* Arrays.copyOf(原数组,复制的长度,指定转换的类型)
*/
String[] array = Arrays.copyOf(obj,obj.length,String[].class);
System.out.println("Map转Array的第一种方法:"+array);
/**
* 第二种方法,直接强制转换数组为指定类型
* 此处toArray()中的参数需要一个T[] a,new String[0]相当于开辟了一个长度为0的String[],并且指定了泛型。
* 这里的用new String[0]只是为了指定函数的形参数,最终返回的String[]的长度是由你的list存储内容的长度决定了。
* new String[0]就是起一个模板的作用,指定了返回数组的类型,0是为了节省空间,因为它只是为了说明返回的类型。
* 因此list.toArray()方法中的参数也可以使用String[0]来指代
*/
String[] array2 =map.values().toArray(new String[0]);
System.out.println("Map转Array的第二种方法:"+array2);
/**
* 第三种方法,使用Java8中Arrays.stream()方法,将对象数组转为顺序Stream,然后使用toArray方法将流的元素累积到新的字符串数组中
* String[]::new 是Java8中新定义的一种写法叫做方法引用,以下这种写法是调用了构造器引用,为了生成一个String类型数组
*/
String[] array3 = Arrays.stream(obj).toArray(String[]::new);
System.out.println("Map转Array的第三种方法:"+array3);
}
Map需要保留key与value时,将Map转为二维数组:
/**
* 第二种:使用for循环和迭代器遍历这个map,将它的key与value逐个添加到一个定长的二维数组中
*/
public static void map_array2(Map<Integer,String> map){
if (map!=null && !map.isEmpty()){
//以map的长度作为二维数组的长度,其中每个元素就是一个长度为2的小数组存放key与value
Object[][] obj = new Object[map.size()][2];
/**
* map.entrySet()是把HashMap类型的数据转换成集合类型
* map.entrySet().iterator()是去获得这个集合的迭代器,保存在iterator里面。
*/
Iterator iterator = map.entrySet().iterator();
for(int i=0;i<map.size();i++){
Map.Entry entry = (Map.Entry) iterator.next();
Object key = entry.getKey();
Object value = entry.getValue();
obj[i][0] = key;
obj[i][1] = value;
}
System.out.println("Map转为二维数组Array:"+obj);
}
}
List转Map:
通常情况下我们从数据库中获取的都是多条数据的list,即多条指定对象格式数据来转换Map。这时候需要使用一个Student(int id,int age,String name,String sex)来辅助我们实现。
//List转Map
/**
*通常情况下我们都是充数据库中查出一个具体对象多条数据的list,以下我们就使用一个Student类来辅助实现
*/
public static void list_map(List<Student> studentList){
//第一种方法:使用for循环遍历list逐个插入map中
Map<Integer,Object> map = new HashMap<>();
for(Student student:studentList){
map.put(student.getId(),student);
}
System.out.println("List转Map的第一种方法:"+map);
/**
* 第二种方法,使用Java8中stream中的Collectors.toMap方法进行转换。
* 如果你的key键没有设定唯一值,防止key键重复,使用Java8新特性中的lambda表达式来表示如果重复,后面就就会覆盖
*/
Map<Integer,String> map2 = studentList.stream().collect
(Collectors.toMap(Student::getId,Student::getName,(key1,key2)->key2));
System.out.println("List转Map的第二种方法:"+map2);
}
Map转List:
Map中的value值转List就直接转换即可
//Map转List
public static void map_list(Map<Integer,String> map){
List<String> list = new ArrayList(map.values());
System.out.println("Map转List:"+list);
}
完整工具类代码:array_map_list
package com.example.demo.utils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author zhangqianwei
* @date 2021/9/6 15:38
*/
public class array_map_list {
//Array、Map、List相互转换
public static void main(String[] args) {
String[] array = {"张三","李四","王五"};
//Array转List
array_list(array);
array_list2(array);
//List转Array
List<String> list = new ArrayList<>();
list.add("手机");
list.add("电脑");
list.add("平板");
list_array(list);
//Array转Map
array_map(array);
String[][] array2 = { { "南京", "江苏" }, { "武汉", "湖北" },
{ "合肥", "安徽" }, { "杭州", "浙江" }, { "长沙", "湖南" } };
array_map2(array2);
//Map转Array
Map<Integer,String> map = new HashMap<>();
map.put(1,"一");
map.put(2,"二");
map.put(3,"三");
map_array(map);
map_array2(map);
//List转Map
Student student = new Student();
student.setId(1);
student.setName("小张");
student.setAge(18);
student.setSex("男");
Student student2 = new Student();
student2.setId(2);
student2.setName("小王");
student2.setAge(19);
student2.setSex("男");
Student student3 = new Student();
student3.setId(3);
student3.setName("小李");
student3.setAge(17);
student3.setSex("女");
List<Student> studentList = new ArrayList<>();
studentList.add(student);
studentList.add(student2);
studentList.add(student3);
list_map(studentList);
//Map转List
map_list(map);
}
//数组Array转List
/**
* 方法一:使用Arrays.asList()方法将数组转为list,不过此种方法有限制,返回的对象是Arrays的内部类
* 对于转换后的list操作仍然反映在原数组上,因此这个list是定长的,无法使用list的add()喝remove()方法
*/
public static void array_list(String[] array){
List<String> list = Arrays.asList(array);
System.out.println("数组转List 的第一种方法:"+list);
// list.remove("李四");
// list.add("刘六");
// System.out.println(“修改后:”list);
}
/**
* 方法二:正常情况下array转换为list,使用for循环将数组中的元素逐个添加到一个空的list中
*/
public static void array_list2(String[] array){
List<String> list = new ArrayList<>();
for (int i=0;i<array.length;i++){
list.add(array[i]);
}
System.out.println("数组转List 的第二种方法:"+list);
list.remove("李四");
list.add("刘六");
System.out.println("修改后:"+list);
}
//List转Array
public static void list_array(List<String> list){
String[] array =list.toArray(new String[list.size()]);
System.out.println("List转数组:"+array);
}
//Array转Map
/**
*一维数组时,奇数位为key键,偶数位为value,如果有奇数个元素,最后一个舍掉
*/
public static void array_map(String[] array) {
Map map = MapUtils.putAll(new HashMap(),array);
System.out.println("数组转Map:"+map);
}
/**
* 二维数组时,当成两个一维数组,使用ArrayUtils.toMap()方法转换
*/
public static void array_map2(String[][] array2){
Map map2 = ArrayUtils.toMap(array2);
map2.put("南昌","江西");
System.out.println("二维数组转Map:"+map2);
}
//Map转Array
/**
* Map只需要value值时,将Map的values转为一维数组
*使用map.values().toArray()将map转为object数组,如果想要转为特定类型的数组需要再进一步转换
*/
public static void map_array(Map<Integer,String> map){
Object[] obj = map.values().toArray();
/**
* 第一种,使用Arrays.copyOf()方法将原数组内的元素拷贝到一个新的String类型的数组
* Arrays.copyOf(原数组,复制的长度,指定转换的类型)
*/
String[] array = Arrays.copyOf(obj,obj.length,String[].class);
System.out.println("Map转Array的第一种方法:"+array);
/**
* 第二种方法,直接强制转换数组为指定类型
* 此处toArray()中的参数需要一个T[] a,new String[0]相当于开辟了一个长度为0的String[],并且指定了泛型。
* 这里的用new String[0]只是为了指定函数的形参数,最终返回的String[]的长度是由你的list存储内容的长度决定了。
* new String[0]就是起一个模板的作用,指定了返回数组的类型,0是为了节省空间,因为它只是为了说明返回的类型。
* 因此list.toArray()方法中的参数也可以使用String[0]来指代
*/
String[] array2 =map.values().toArray(new String[0]);
System.out.println("Map转Array的第二种方法:"+array2);
/**
* 第三种方法,使用Java8中Arrays.stream()方法,将对象数组转为顺序Stream,然后使用toArray方法将流的元素累积到新的字符串数组中
* String[]::new 是Java8中新定义的一种写法叫做方法引用,以下这种写法是调用了构造器引用,为了生成一个String类型数组
*/
String[] array3 = Arrays.stream(obj).toArray(String[]::new);
System.out.println("Map转Array的第三种方法:"+array3);
}
/**
* 第二种:使用for循环和迭代器遍历这个map,将它的key与value逐个添加到一个定长的二维数组中
*/
public static void map_array2(Map<Integer,String> map){
if (map!=null && !map.isEmpty()){
//以map的长度作为二维数组的长度,其中每个元素就是一个长度为2的小数组存放key与value
Object[][] obj = new Object[map.size()][2];
/**
* map.entrySet()是把HashMap类型的数据转换成集合类型
* map.entrySet().iterator()是去获得这个集合的迭代器,保存在iterator里面。
*/
Iterator iterator = map.entrySet().iterator();
for(int i=0;i<map.size();i++){
Map.Entry entry = (Map.Entry) iterator.next();
Object key = entry.getKey();
Object value = entry.getValue();
obj[i][0] = key;
obj[i][1] = value;
}
System.out.println("Map转为二维数组Array:"+obj);
}
}
//List转Map
/**
*通常情况下我们都是充数据库中查出一个具体对象多条数据的list,以下我们就使用一个Student类来辅助实现
*/
public static void list_map(List<Student> studentList){
//第一种方法:使用for循环遍历list逐个插入map中
Map<Integer,Object> map = new HashMap<>();
for(Student student:studentList){
map.put(student.getId(),student);
}
System.out.println("List转Map的第一种方法:"+map);
/**
* 第二种方法,使用Java8中stream中的Collectors.toMap方法进行转换。
* 如果你的key键没有设定唯一值,防止key键重复,使用Java8新特性中的lambda表达式来表示如果重复,后面就就会覆盖
*/
Map<Integer,String> map2 = studentList.stream().collect
(Collectors.toMap(Student::getId,Student::getName,(key1,key2)->key2));
System.out.println("List转Map的第二种方法:"+map2);
}
//Map转List
public static void map_list(Map<Integer,String> map){
List<String> list = new ArrayList(map.values());
System.out.println("Map转List:"+list);
}
}
结果显示: