Java 有没有更有效的方法在ArrayList和Array之间进行转换

Java 有没有更有效的方法在ArrayList和Array之间进行转换,java,arrays,performance,arraylist,Java,Arrays,Performance,Arraylist,使用Java,我有一个类,它以字节数组的形式检索网页。然后我需要去掉一些内容,如果它存在的话。(应用程序监视网页的更改,但需要从php创建的html中删除会话ID,这意味着每次访问网页时都会检测到更改) 某些结果字节数组的长度可能是10秒或1000秒字节。它们不是这样存储的——存储的是页面的16字节MD5。但是,需要处理的是原始的全尺寸字节数组 (更新-代码不起作用。请参阅下面A.H.的评论) 显示我的代码的测试: public void testSessionIDGetsRemovedFrom

使用Java,我有一个类,它以字节数组的形式检索网页。然后我需要去掉一些内容,如果它存在的话。(应用程序监视网页的更改,但需要从php创建的html中删除会话ID,这意味着每次访问网页时都会检测到更改)

某些结果字节数组的长度可能是10秒或1000秒字节。它们不是这样存储的——存储的是页面的16字节MD5。但是,需要处理的是原始的全尺寸字节数组

更新-代码不起作用。请参阅下面A.H.的评论) 显示我的代码的测试:

public void testSessionIDGetsRemovedFromData() throws IOException
    {

        byte[] forumContent = "<li class=\"icon-logout\"><a href=\"./ucp.php?mode=logout&amp;sid=3a4043284674572e35881e022c68fcd8\" title=\"Logout [ barry ]\" accesskey=\"x\">Logout [ barry ]</a></li>".getBytes();

        byte[] sidPattern = "&amp;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&amp;sid=3a4043284674572e35881e022c68fcd8\" title=\"Logout [ barry ]\" accesskey=\"x\">Logout [ barry ]</a></li>";
        String sidPattern = "&amp;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&amp;sid=3a4043284674572e35881e022c68fcd8\" title=\"Logout [ barry ]\" accesskey=\"x\">Logout [ barry ]</a>&amp;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("&amp;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&amp;sid=3a4043284674572e35881e022c68fcd8\" title=\"Logout [ barry ]\" accesskey=\"x\">Logout [ barry ]</a>&amp;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("&amp;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