Java 有没有更有效的方法在ArrayList和Array之间进行转换
使用Java,我有一个类,它以字节数组的形式检索网页。然后我需要去掉一些内容,如果它存在的话。(应用程序监视网页的更改,但需要从php创建的html中删除会话ID,这意味着每次访问网页时都会检测到更改) 某些结果字节数组的长度可能是10秒或1000秒字节。它们不是这样存储的——存储的是页面的16字节MD5。但是,需要处理的是原始的全尺寸字节数组 (更新-代码不起作用。请参阅下面A.H.的评论) 显示我的代码的测试:Java 有没有更有效的方法在ArrayList和Array之间进行转换,java,arrays,performance,arraylist,Java,Arrays,Performance,Arraylist,使用Java,我有一个类,它以字节数组的形式检索网页。然后我需要去掉一些内容,如果它存在的话。(应用程序监视网页的更改,但需要从php创建的html中删除会话ID,这意味着每次访问网页时都会检测到更改) 某些结果字节数组的长度可能是10秒或1000秒字节。它们不是这样存储的——存储的是页面的16字节MD5。但是,需要处理的是原始的全尺寸字节数组 (更新-代码不起作用。请参阅下面A.H.的评论) 显示我的代码的测试: public void testSessionIDGetsRemovedFrom
public void testSessionIDGetsRemovedFromData() throws IOException
{
byte[] forumContent = "<li class=\"icon-logout\"><a href=\"./ucp.php?mode=logout&sid=3a4043284674572e35881e022c68fcd8\" title=\"Logout [ barry ]\" accesskey=\"x\">Logout [ barry ]</a></li>".getBytes();
byte[] sidPattern = "&sid=".getBytes();
int sidIndex = ArrayCleaner.getPatternIndex(forumContent, sidPattern);
assertEquals(54, sidIndex);
// start of cleaning code
ArrayList<Byte> forumContentList = new ArrayList<Byte>();
forumContentList.addAll(forumContent);
forumContentList.removeAll(Arrays.asList(sidPattern));
byte[] forumContentCleaned = new byte[forumContentList.size()];
for (int i = 0; i < forumContentCleaned.length; i++)
{
forumContentCleaned[i] = (byte)forumContentList.get(i);
}
//end of cleaning code
sidIndex = ArrayCleaner.getPatternIndex(forumContentCleaned, sidPattern);
assertEquals(-1, sidIndex);
}
public void testsessionidgesremovedfromdata()引发IOException
{
byte[]forumContent=“”。getBytes();
byte[]sidPattern=“&;sid=“.getBytes();
int-sideindex=ArrayCleaner.getPatternIndex(forumContent,sidPattern);
资产质量(54,SIDDINDEX);
//开始清理代码
ArrayList forumContentList=新的ArrayList();
forumContentList.addAll(forumContent);
removeAll(Arrays.asList(sidPattern));
byte[]forumContentCleaned=新字节[forumContentList.size()];
for(int i=0;i
这一切都很好,但我担心的是清洁部分的效率。我本来希望只对数组进行操作,但是ArrayList有很好的内置函数,可以从ArrayList等中删除集合,这正是我所需要的。因此,我必须创建一个字节的ArrayList,因为我不能拥有原始字节的ArrayList(有人能告诉我为什么吗?),请将要删除的模式转换为另一个ArrayList(我想这可能一直都是ArrayList)以传递给removeAll()。然后我需要创建另一个字节[],并将字节数组列表中的每个元素转换为一个字节,然后将其添加到字节[]
有没有更有效的方法来做这一切?
可以使用数组执行吗
更新
这与使用字符串的功能相同:
public void testSessionIDGetsRemovedFromDataUsingStrings() throws IOException
{
String forumContent = "<li class=\"icon-logout\"><a href=\"./ucp.php?mode=logout&sid=3a4043284674572e35881e022c68fcd8\" title=\"Logout [ barry ]\" accesskey=\"x\">Logout [ barry ]</a></li>";
String sidPattern = "&sid=";
int sidIndex = forumContent.indexOf(sidPattern);
assertEquals(54, sidIndex);
forumContent = forumContent.replaceAll(sidPattern, "");
sidIndex = forumContent.indexOf(sidPattern);
assertEquals(-1, sidIndex);
}
public void TestSessionIdgetRemovedFromDataUsingStrings()引发IOException
{
字符串forumContent=“”;
字符串sidPattern=“&;sid=”;
int-sideindex=forumContent.indexOf(sidPattern);
资产质量(54,SIDDINDEX);
forumContent=forumContent.replaceAll(sidPattern,“”);
sidIndex=forumContent.indexOf(sidPattern);
资产质量(-1,SIDDINDEX);
}
这和array/arrayList方法一样有效吗
谢谢,
Barry您可以使用它将任何列表转换为数组
在这个特定的用例中,情况要复杂一些,因为在转换列表时,没有优雅的方法自动取消装箱(从字节
到字节
)。好的ol'Java泛型。这是一个很好的进入
所以我必须创建一个字节的ArrayList,因为我不能有一个原始字节的ArrayList(有人能告诉我为什么吗?)
因为在Java中,泛型类型参数不能是原语。看
旁注:就风格而言,您几乎应该始终将
ArrayList
类型声明为List
:
List<Byte> forumContentList = new ArrayList<Byte>();
List-forumContentList=new-ArrayList();
见和
这一切都很好,我担心清洁部门的效率
真的吗?你检查过结果“字符串”了吗?在我的机器上,forumContentCleaned
中的数据仍然包含&;sid=…
数据
那是因为
forumContentList.removeAll(Arrays.asList(sidPattern));
尝试从列表中删除列表
。这没有用。即使您将removeAll
的参数替换为包含“&;sid=“
”字节的真实列表,您也将删除每个a
、每个m
、每个p
等的所有事件。结果数据如下所示:
<l cl"con-logout">< href"./uc.h?oelogout34043284674572e35881e022c68fc8" ttle....
编辑2
下面是StringBuilder
和String.replaceAll
之间的一个小基准:
public class ReplaceAllBenchmark {
public static void main(String[] args) throws Throwable {
final int N = 1000000;
String input = "<li class=\"icon-logout\"><a href=\"./ucp.php?mode=logout&sid=3a4043284674572e35881e022c68fcd8\" title=\"Logout [ barry ]\" accesskey=\"x\">Logout [ barry ]</a>&sid=3a4043284674572e35881e022c68fcd8\"</li>";
stringBuilderBench(input, N);
regularExpressionBench(input, N);
}
static void stringBuilderBench(String input, final int N) throws Throwable{
for(int run=0; run<5; ++run){
long t1 = System.nanoTime();
for(int i=0; i<N; ++i)
removeSecrets(input);
long t2 = System.nanoTime();
System.out.println("sb: "+(t2-t1)+"ns, "+(t2-t1)/N+"ns/call");
Thread.sleep(1000);
}
}
static void regularExpressionBench(String input, final int N) throws Throwable{
for(int run=0; run<5; ++run){
long t1 = System.nanoTime();
for(int i=0; i<N; ++i)
removeSecrets2(input);
long t2 = System.nanoTime();
System.out.println("regexp: "+(t2-t1)+"ns, "+(t2-t1)/N+"ns/call");
Thread.sleep(1000);
}
}
static String removeSecrets2(String input){
return input.replaceAll("&sid=[^\"]*\"", "\"");
}
}
我不认为两个代码有相同的功能
第一个代码从forumContent中删除sidPattern中的所有字符。
第二段代码从ForumConnt中删除sidPattern字符串,可能不起作用,因为replaceAll()将参数作为正则表达式模式接受
是否确实要删除“&sid=”而不是“&sid=3a4043284674572e35881e022c68fcd8”
无论如何,我认为字符串很好,列表有点重。我只是好奇像Jsoup这样的网页解析器是否能更好地工作。为什么要使用字节数组而不是字符串?错误。。。老实说,我想不出一个好的答案。我认为使用byte[]将这些数据存储在数据库中感觉很自然。使用字符串不会占用更多内存吗?您还需要回答我的问题:为什么不简单地剥离您希望使用Jsoup或类似web解析器检查的数据?好吧,在回答这个问题之前,我必须先检查一下。如果有一个现有的组件可以完成这项工作,那就太好了,谢谢你的指针。我现在正在处理它。。。为发布不可靠的代码致歉:-(+1顺便说一句,当我发布问题时,测试确实通过了,但后来我意识到我在forumContentList.addAll(forumContentList);line上犯了一个错误。我实际上粘贴了forumContentList.addAll(forumContentList);这是胡说八道,但我得到了JUnit绿线:-/没有借口,我知道…我已经看过StringBuilder,但我认为String看起来更适合我的需要,因为replaceAll()方法正是我需要的。如果使用public class ReplaceAllBenchmark {
public static void main(String[] args) throws Throwable {
final int N = 1000000;
String input = "<li class=\"icon-logout\"><a href=\"./ucp.php?mode=logout&sid=3a4043284674572e35881e022c68fcd8\" title=\"Logout [ barry ]\" accesskey=\"x\">Logout [ barry ]</a>&sid=3a4043284674572e35881e022c68fcd8\"</li>";
stringBuilderBench(input, N);
regularExpressionBench(input, N);
}
static void stringBuilderBench(String input, final int N) throws Throwable{
for(int run=0; run<5; ++run){
long t1 = System.nanoTime();
for(int i=0; i<N; ++i)
removeSecrets(input);
long t2 = System.nanoTime();
System.out.println("sb: "+(t2-t1)+"ns, "+(t2-t1)/N+"ns/call");
Thread.sleep(1000);
}
}
static void regularExpressionBench(String input, final int N) throws Throwable{
for(int run=0; run<5; ++run){
long t1 = System.nanoTime();
for(int i=0; i<N; ++i)
removeSecrets2(input);
long t2 = System.nanoTime();
System.out.println("regexp: "+(t2-t1)+"ns, "+(t2-t1)/N+"ns/call");
Thread.sleep(1000);
}
}
static String removeSecrets2(String input){
return input.replaceAll("&sid=[^\"]*\"", "\"");
}
}
java version "1.6.0_20"
OpenJDK Runtime Environment (IcedTea6 1.9.9) (6b20-1.9.9-0ubuntu1~10.04.2)
OpenJDK 64-Bit Server VM (build 19.0-b09, mixed mode)
sb: 538735438ns, 538ns/call
sb: 457107726ns, 457ns/call
sb: 443282145ns, 443ns/call
sb: 453978805ns, 453ns/call
sb: 458895308ns, 458ns/call
regexp: 2404818405ns, 2404ns/call
regexp: 2196834572ns, 2196ns/call
regexp: 2239056178ns, 2239ns/call
regexp: 2164337638ns, 2164ns/call
regexp: 2177091893ns, 2177ns/call