数组转集合、集合转数组、字符串数组与int型、long型数组
等的转换以及排序问题
==================类型转换==================
在项⽬中经常会遇到数组转集合、集合转数组、数组之间类型转换等操作
1.数组转集合
为了实现把⼀个数组转换成⼀个ArrayList,很多Java程序员会使⽤如下的代码:
String str[] = {"1","2","3"};
List<String> strings = Arrays.asList(str);
Arrays.asList确实会返回⼀个ArrayList对象,但是该类是Arrays类中⼀个私有静态内部类,⽽不是常见的java.util.ArrayList 类。这个java.util.Arrays.ArrayList类具有 set(),get(),contains()等⽅法,但是不具有任何添加或移除元素的任何⽅法。因为该类的⼤⼩(size)是固定的。如果添加元素是会报错的(但是如果转换后的集合只是⽤来进⾏查询不进⾏增加元素也可以这样转换):
String str[] = {"1","2","3"};
List<String> strings = Arrays.asList(str);
strings.add("eee");
报错如下:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
st1(Test.java:31)
at Test.main(Test.java:24)
为了创建出⼀个真正的ArrayList,代码应该如下所⽰:(这种⽅法创建的集合可以进⾏集合的增加)
String str[] = {"1","2","3"};
List<String> strings = new ArrayList<String>(Arrays.asList(str));
strings.add("4");
System.out.println(strings);
更加⾼效的代码如下:
String str[] = {"1","2","3"};数组转换成字符串
List<String> strings = new ArrayList<String>(str.length);
Collections.addAll(strings,str);
strings.add("4");
System.out.println(strings);
2.集合转数组
(1)错误演⽰
很多⼈习惯下⾯⽤法:
List<String> strings = new ArrayList<String>();
String[] objects = (String[]) Array();
编译通过,运⾏报错如下:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
st1(Test.java:32)
at Test.main(Test.java:26)
学过JVM的应该知道上⾯的意思是Object数组不能转变为String数组。[代表以为数组,L代表数组的元素是引⽤类型,后⾯是具体的元素类型
对于这个现象我们可以这么解释:Java中允许向上和向下转型,但是这个转型是否成功是根据Java虚拟机中这个对象的类型来实现的。Java虚拟机中保存了每个对象的类型。⽽数组也是⼀个对象。数
组的类型是[Ljava.lang.Object。把[Ljava.lang.Object转换成 [Ljava.lang.String是显然不可能的事情,因为这⾥是⼀个向下转型,⽽虚拟机只保存了这是⼀个Object的数组,不能保证数组中的元素是String的,所以这个转型不能成功。数组⾥⾯的元素只是元素的引⽤,不是存储的具体元素,所以数组中元素的类型还是保存在Java虚拟机中的。
根据上⾯的解释,我们可以把这个问题归纳到下⾯这个模型:
Object objs[]=new Object[10];
String strs[]=(String[])objs;
这样⼦和刚才上⾯编译错误是⼀样的。如果我们修改⼀下这个代码,如下:
String strs[]=new String[10];
Object objs[]=strs;
这样⼦就可以编译通过了。所以这个问题我们可以归结为⼀个Java转型规则的问题。
(2)正确的做法:(延伸⼀点直接打印数组打印的是数组的)
最菜鸡的做法是:
List<String> list = new ArrayList<String>();
list.add("1");
String strings[]=new String[list.size()];
for(int i=0,j=list.size();i<j;i++){
strings[i]=(i);
}
System.out.println(strings);
System.out.Class());
System.out.String(strings));
结果:
[Ljava.lang.String;@20724356
class [Ljava.lang.String;
[1]
⽐较简便的做法:
List<String> list = new ArrayList<String>();
list.add("1");
String[] strings = new String[list.size()];
System.out.println(strings);
System.out.Class());
System.out.String(strings));
结果同上。
3.数组转数组--代码⽤到了commons-beanutils包
最常见的就是字符串数组类型转int、long数组,或者字符串类型转Integer、Long、Integer型转int(也就是包装类型转原始类型)。最原始的for循环转换赋值在这⾥就不试了。
数组类型的转换:
import org.apachemons.beanutils.ConvertUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Test {
public static void main(String[] args) {
String str[] = { "1", "2", "3" };
// 字符串数组转long数组
long[] str2lon = (long[]) vert(str, long.class);
System.out.println(str2lon);
// 字符串数组转Long数组
Long[] str2Lon = (Long[]) vert(str, Long.class);
System.out.println(str2Lon);
// 字符串数组转int数组
int[] str2int = (int[]) vert(str, int.class);
System.out.println(str2int);
// 字符串数组转Integer数组
Integer[] str2Int = (Integer[]) vert(str, Integer.class);
System.out.println(str2Int);
// int型数组转为String数组
String int2Str[] = (String[]) vert(str2int, String[].class);
System.out.println(int2Str);
// Integer型数组转为String数组
String Int2Str[] = (String[]) vert(str2Int, String[].class);
System.out.println(Int2Str);
// long型数组转为String数组
String lon2str[] = (String[]) vert(str2lon, String[].class);
System.out.println(lon2str);
String Lon2str[] = (String[]) vert(str2Lon, String[].class);
System.out.println(Lon2str);
}
}
[J@15a6d5e1
[Ljava.lang.Long;@7c23b1e1
[I@b736a73
[Ljava.lang.Integer;@4651a9e4
[Ljava.lang.String;@1b68dbcd
[Ljava.lang.String;@1367dca
[Ljava.lang.String;@207c5965
[Ljava.lang.String;@43d1068c
关于包装类型转原始类,可以⽤commons-lang包的ArrayUtils操作,参考:
补充:补充⼀点JVM相关知识
在Java中,任何类型都有class,包括基本数据类型与void。在Java中 [ 代表数组, [[ 代表⼆维数组。依次类推。
其他的描述标识符如下:
B---基本数据类型byte
C---基本数据类型char
D---基本数据类型double
F---基本数据类型float
I---基本数据类型int
J---基本数据类型long
S---基本数据类型short
Z---基本数据类型boolean
V---特殊类型void
L---对象类型(也就是引⽤类型)。例如 Ljava/lang/Object.
需要注意的是⼋种基本数据类型也有 calss,⽽且其对应包装类型有⼀个TYPE成员变量就是其基本数据类型。特殊类型void也有class。基本类型的数组与引⽤类型数组也都有class
public static final Class<Integer> TYPE = (Class<Integer>) PrimitiveClass("int");
例如:
System.out.println(int.class);
System.out.println(Integer.class);
System.out.println(Integer.TYPE);
System.out.println(Integer[].class);
System.out.println(int[].class);
System.out.println(void.class);
结果:
int
class java.lang.Integer
int
class [Ljava.lang.Integer;
class [I
void
注意int不是对象,所以没有getClass⽅法。只有int.class
==================数组与集合排序==================
JDK⾃带的排序⽅法可以满⾜⼤部分要求。我们知道要在集合中排序,需要使⽤可以排序的集合或者⾃⼰⼿动排序。使⽤可排序的集合如TreeMap,TreeSet。如果⼿动排序就是⽤Collections.sort传⼊⼀个⽐较器即可。
1.数组排序
在使⽤Arrays.sort()对int、double、long等基本类型的数组进⾏排序时,只有正序排序的⽅法。要实现倒序排序,只有使⽤Integer、Double、Long等代替。
包装类型⽐较的时候可以传⼊⽐较器,如下:
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
public class PlainTest {
public static void main(String[] args) {
/
/ 基本数据类型Arrays.sort正序
char[] chars = { 'a', 'b', 'd', 'e', 'c', 'e', 'd', 'a' };
Arrays.sort(chars);
System.out.println(chars);
// 原⽣数组正序
Character[] characters = { 'a', 'b', 'd', 'e', 'c', 'e', 'd', 'a' };
Arrays.sort(characters);
System.out.String(characters));
// 原⽣数组逆序
Arrays.sort(characters, verseOrder());
System.out.String(characters));
/
/ ⾃⼰实现逆序号排序
Arrays.sort(characters, new Comparator<Character>() {
@Override
public int compare(Character o1, Character o2) {
if (o1 > o2) {
return -1;
} else if (o1 < o2) {
return 1;
}
return 0;
}
});
System.out.String(characters));
}
}
结果:
aabcddee
[a, a, b, c, d, d, e, e]
[e, e, d, d, c, b, a, a]
[e, e, d, d, c, b, a, a]
查看源码:(逆序是通过反转compare来实现的)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论