Thursday, July 17, 2025

ByteArrayBuilder: A simplfied version of java.nio.ByteBuffer

I was doing some work in video streaming from mobile phones to PC recently and I was dealing with a lot of byte array streams from client to server, which I also needed to collocate on the server side. 

I decided to write a class that simplifies the whole process, making the array management process as simple as using StringBuilder in Java; but for byte arrays.

"Why did you need to do that when you could use java.nio.ByteBuffer?" you may ask me, but well sometimes you need something simpler in usage and well you wonder secretly, if you can do it faster.

So I wrote ByteArrayBuilder.java
I didn't think of benchmarking it that much since I had little thought about it. I was more focused on the ease of use.

Recently however, I asked Github Copilot to analyze the file and it told me a lot about it, including the fact that I was better off with using java.nio.ByteBuffer . What I was doing was tantamount to reinventing the wheel according to the AI. It also advised me to run benchmarks of ByteArrayBuilder.java against java.nio.ByteBuffer. And that was what I did.

I wrote a benchmark found at: ByteArrayBuilderWars.java
Here are the results:


I sent a  number of byte arrays say 
numberOfArrays
and each of these byte arrays had a size of
dataArraySize

public static void main(String[] args) throws IOException {

        int dataArraySize = 10000;
        int numberOfArrays = 100000;
        
        for (int i = 0; i < 10; i++) {
            ByteArrayBuilder builder = ByteArrayBuilderWars.benchmarkAppendForByteArrayBuilder(dataArraySize, numberOfArrays);
            ByteBuffer buffer = ByteArrayBuilderWars.benchmarkAppendForByteBuffer(dataArraySize, numberOfArrays);

            ByteArrayBuilderWars.benchmarkReadBytes(builder);
            ByteArrayBuilderWars.benchmarkReadBytes(buffer);
        }

    }
Here are the results:

  
RESULTS for append ops(ms)
arraySizenumArraysByteArrayBuilder(ms)java.nio.ByteBuffer(ms)
1000010022.16614.363
1000010011.3610.988
1000010012.4311.959
1000010010.38211.187
1000010011.04111.182
RESULTS for bytes-reader ops(ms)
arraySizenumArraysByteArrayBuilder(ms)java.nio.ByteBuffer(ms)
100001000.0050.477
100001000.0090.737
100001000.0050.589
100001000.0060.154
100001000.0050.146
RESULTS for append ops(ms)
arraySizenumArraysByteArrayBuilder(ms)java.nio.ByteBuffer(ms)
100001000120.38110.924
100001000104.201105.941
100001000103.048102.265
100001000103.61102.372
100001000102.899101.902
RESULTS for bytes-reader ops(ms)
arraySizenumArraysByteArrayBuilder(ms)java.nio.ByteBuffer(ms)
1000010000.0085.089
1000010000.0062.847
1000010000.0052.734
1000010000.0052.896
1000010000.0072.681
RESULTS for append ops(ms)
arraySizenumArraysByteArrayBuilder(ms)java.nio.ByteBuffer(ms)
10000100001106.5891077.174
10000100001023.7011012.844
10000100001067.0481041.951
10000100001049.6631029.896
10000100001069.8671046.699
RESULTS for bytes-reader ops(ms)
arraySizenumArraysByteArrayBuilder(ms)java.nio.ByteBuffer(ms)
10000100000.00530.745
10000100000.00622.519
10000100000.00324.707
10000100000.00324.299
10000100000.00325.242


The results say it all. I ran each result row and took the average of 10 samples of the quantity being measured, then I recorded 5 samples of the said average.




The append rates are very much similar, though java.nio.ByteBuffer consistently outperforms ByteArrayBuilder, even though, it is ever so slightly.

There are at least 3 instances though where the ByteArrayBuilder outperforms the java.nio.ByteBuffer
, even though the difference once again is ever so minute.

When it comes to reading the bytes though, it is a classic massacre.
The ByteArrayBuilder is thousands of time faster than the java.nio.ByteBuffer every single time.
This is because when well written, the ByteArrayBuilder has the array to be read at the ready and simply returns it.

So Github Copilot, sorry ByteArrayBuilder  is a much better choice than the java.nio.ByteBuffer for simple byte array collocation and reading.

Thanks guys.

You can view the class and its benchmarks on Github at ByteArrayBuilder.java  and

 ByteArrayBuilderWars.java , respectively


 

Monday, September 11, 2017

LinkedList implementation in C with java.util.ArrayList like sublist capability

Place this in an header file, called list.h

/*
 * File:   list.h
 * Author: hp
 *
 * Created on September 3, 2017, 2:41 AM
 */

#ifndef LIST_H
#define    LIST_H

#ifdef    __cplusplus
extern "C" {
#endif




 typedef struct Node {
    struct Node* next;
    struct Node* prev;
    void* val;
 }Node;

 typedef struct List {
     int length;
    struct Node* firstNode;
    struct Node* lastNode;
    struct List* subList;

    struct List* parent;

    //This indices are -1 if the sublist field is NULL
    int startIndex;
    int endIndex;
}List;

List* newList();
Node* initNode(Node* prev, void* val, Node* next);
void ToArray(List* list,void* result[]) ;
void addNode(List* list,Node *elem);
void AddArray(List* list, void* *array, int len);
void Add(List* list,void* val);
bool addNodeAt(List* list,Node* elem,int index );
bool AddVal(List* list,void* val, int index);
bool removeNode(List* list,Node* elem);
void RemoveAll(List* list,List* lst);
bool AddAll(List* list,List* lst);
bool IsEmpty(List* list);
bool AddAllAt(List* list,int index, List *lst);
bool Remove(List* list,void* val);
bool RemoveIndex(List* list,int index);
List* SubList(List* list,int startIndex, int endIndex);
Node* getNode(List* list,int index);
void* Get(List* list,int index);
Node* getLastNode(List* list);
void* LastElement(List* list);
int IndexOf(List* list,void* val);
bool isSubList(List* list);
/**
 *
 * Pass the list and an empty array of size 2. When the function returns, the array contains pointers to the boundary nodes
 */
void getBoundaryNodes(List* list,Node* bounds[]);
int indexOfNode(List* list,Node* node);
bool containsNode(List* list,Node* node);
void prepend(List* list,void* val);
 void append(List* list,void* val);
Node* insertBefore(List* list,void* e, Node* succ);
 Node* insertAfter(List* list, void* e, Node* succ);
bool Contains(List* list,void* val);


void Clear(List* list);
void removeLinkedRange(List* list, Node* startNode, Node* stopNode);
void Log(List* list,char* optionalLabel);

void syncRemoval(List* list, int index);
void syncAdditions(List* list, int index);
char* concatStrAndInt(char* str, int val);
 char* concat(char*str, char* str1);
 char* prependInt(int num, char* str2);
 char* appendInt( char* str , int num);
 char* concatOnInt( char* str , int num, char* str2);
 

   
   

#ifdef    __cplusplus
}
#endif

#endif    /* LIST_H */





Now, save this in another file called list.c





#include
#include
#include




This is the code for the doubly-linked linked list.

Now create a c file called listmain.c  that will test the list:



void quickAddInt(List* list , int num){
    void* num_ptr = #
    Add(list , num_ptr);
}

int main() {
   
    List* list = newList();
 
 
 
 
    Add(list, (void *)3);
    Add(list, (void *)8);
   
      srand(time(0));
        int TEST_SIZE = 25;

    int n = 200000;
    /* Assign pointers into appropriate parts of matrix. */
        for (int i = 0; i < TEST_SIZE; i++) {
            int rnd = rand() % n;
            void* p = &rnd;
          Add(list , p);
        }
 
    List* small_list = SubList(list , 5 , 12);
 
    Log(list, "LIST");
    Log(small_list, "SUB list");
 
    Clear(small_list);
 
 
    Log(list, "AFTER CLEARING SUB, list");
    Log(small_list, "SUB list");
   
   
 
    List* second = newList();
    quickAddInt(second , 5);
    quickAddInt(second , 205);
    quickAddInt(second , 502);
    quickAddInt(second , 45);
    quickAddInt(second , 67);
    quickAddInt(second , 99);
    quickAddInt(second , 510);
    quickAddInt(second , 1020);
    quickAddInt(second , 5008);
    quickAddInt(second , 30042);
    quickAddInt(second , 20014);
    quickAddInt(second , 30041);
    quickAddInt(second , 10518902); 
         
    Log(second, "SECOND list");
 
    AddAll(small_list, second);
 
 
    Log(small_list, "ADD second_list to SUB list...SUB list is now");
    Log(list, "LIST is now");
 
 
    void* arr[9] = {(void*)10,(void*)4,(void*)1,(void*)9,(void*)8,(void*)12,(void*)34,(void*)4,(void*)58};
    int siz = sizeof(arr)/sizeof(arr[0]);
    AddArray( small_list , arr, siz );
 
 
 
 
    Log(small_list, "AddValues called on SUB list...SUB list is now");
    Log(list, "LIST is now");
   
  void* array[4] = {(void*)1245,(void*)90,(void*)42,(void*)89};
    AddArray(list , array ,4);
 
    Log(list, "LIST");
 
    RemoveAll(list, SubList(second,0,7));
 
    Log(list, "LIST");
 

    return (EXIT_SUCCESS);
}





Wednesday, August 30, 2017

A simple LinkedList in GoLang that you can use like java.util.ArrayList

// golist
package main

import (
    "fmt"
    "reflect"
    "strconv"
)

type AbstractList interface {
    newList()
    ToArray() []interface{}
    addNode(elem *Node)
    Add(val interface{})
    addNodeAt(elem *Node, index int) bool
    AddVal(val interface{}, index int) bool
    removeNode(elem *Node) bool
    RemoveAll(lst *List)
    AddAll(lst *List)
    IsEmpty() bool
    AddAllAt(index int, lst *List)
    Remove(val interface{}) bool
    RemoveIndex(index int) bool
    SubList(startIndex int, endIndex int) *List
    getNode(index int) *Node
    Get(index int) interface{}
    getLastNode() *Node
    LastElement() interface{}
    IndexOf(val interface{}) int
    Contains(val interface{}) bool
    Clear()
    Log()
}

type Node struct {
    next *Node
    prev *Node
    val  interface{}
}

type List struct {
    length    int
    firstNode *Node
    lastNode  *Node
    subList   *List

    parent *List

    //This indices are -1 if the sublist field is nil
    startIndex int
    endIndex   int
}

func (list *List) newList() {
    list.length = 0
    list.firstNode = nil
    list.lastNode = nil
    list.subList = nil
    list.parent = nil
    list.startIndex = -1
    list.endIndex = -1
}
func (node *Node) initNode(prev *Node, val interface{}, next *Node) {
    node.prev = prev
    node.next = next
    node.val = val
}

//[]int{1,4,293,4,9}
//TESTED
func (list *List) ToArray() []interface{} {

    if list.isSubList() {

        result := make([]interface{}, list.length)

        if len(result) == 0 {
            return result
        }

        i := 0
        for x := list.parent.getNode(list.startIndex); i < list.length; x = x.next {
            result[i] = x.val
            i++
        }
        return result
    } else {

        result := make([]interface{}, list.length)

        i := 0
        for x := list.firstNode; i < list.length; x = x.next {
            result[i] = x.val
            i++
        }
        return result
    }

}

//TESTED
func (list *List) addNode(elem *Node) {

    if list.isSubList() {

        list.parent.addNodeAt(elem, list.endIndex)
        list.length++
        list.endIndex++

    } else {

        oldLastNode := list.lastNode

        list.lastNode = elem
        if oldLastNode == nil {
            list.firstNode = elem
        } else {
            oldLastNode.next = elem
            elem.prev = oldLastNode
        }
        list.length++

    }
}

//TESTED
func (list *List) AddValues(args ...interface{}) {
    if list.isSubList() {

        endNode := new(Node)
        skipFirst := false

        if list.IsEmpty() {
            if list.startIndex == 0 {
                endNode = list.parent.insertBefore(args[0], list.parent.firstNode)
                list.parent.length++
                list.length++
                list.endIndex++
                skipFirst = true
            } else {
                endNode = list.parent.getNode(list.startIndex - 1)
            }

        } else {
            endNode = list.getNode(list.length - 1)
        }
        i := 0
        if skipFirst {
            i = 1
        }
        for ; i < len(args); i++ {
            endNode = list.parent.insertAfter(args[i], endNode)
            list.parent.length++
            list.length++
            list.endIndex++
        }

    } else {
        for i := 0; i < len(args); i++ {
            list.append(args[i])
        }
    }

}

//TESTED
func (list *List) AddArray(array []interface{}) {
    list.AddValues(array)
}

//TESTED
func (list *List) Add(val interface{}) {
    if list.isSubList() {

        if list.length == 0 {
            list.parent.AddVal(val, list.startIndex)
        } else {
            list.parent.AddVal(val, list.endIndex)
        }
        //list.parent.AddVal(val, list.endIndex+1)
        list.length++
        list.endIndex++
    } else {
        list.append(val)
    }

}

/**
 *
 *  Only parent lists should ever call this function!
 */
//TESTED
func (list *List) addNodeAt(elem *Node, index int) bool {

    if list.parent == nil {
        if index == list.length {
            list.addNode(elem)
        } else {

            succ := list.getNode(index)

            // assert succ != nil;
            prev := succ.prev

            elem.prev = succ.prev
            elem.next = succ
            succ.prev = elem

            if prev == nil {
                list.firstNode = elem
            } else {
                prev.next = elem
            }
            list.length++
        }
        list.syncAdditions(index)

        return true
    }
    return false

}

//TESTED
func (list *List) AddVal(val interface{}, index int) bool {

    if list.isSubList() {
        success := list.parent.AddVal(val, index+list.startIndex)
        list.length++
        list.endIndex++
        return success

    } else {
        elem := new(Node)
        elem.next = nil
        elem.val = val

        return list.addNodeAt(elem, index)
    }

}

func (list *List) removeNode(elem *Node) bool {

    if list.isSubList() {

        if list.containsNode(elem) {

            succ := list.parent.removeNode(elem)
            list.length--
            list.endIndex--
            return succ

        }
        return false
    } else {

        next := elem.next
        prev := elem.prev

        if prev == nil {
            list.firstNode = next
        } else {
            prev.next = next
            elem.prev = nil
        }

        if next == nil {
            list.lastNode = prev
        } else {
            next.prev = prev
            elem.next = nil
        }

        elem.val = nil
        list.length--
        return true
    }

}

//TESTED
func (list *List) RemoveAll(lst *List) {
    //empty list
    if lst.firstNode == nil {
        return
    }

    if list.isSubList() {

        x := new(Node)
        if lst.isSubList() {
            x = lst.getNode(0)
        } else {
            x = lst.firstNode
        }

        for i := 0; i < lst.length; i++ {
            list.Remove(x.val)
            x = x.next
        }

    } else {

        x := new(Node)
        if lst.isSubList() {
            x = lst.getNode(0)
        } else {
            x = lst.firstNode
        }
        for i := 0; i < lst.length; i++ {
            list.Remove(x.val)
            x = x.next
        }

    }
}

//TESTED
func (list *List) AddAll(lst *List) bool {

    //empty list

    if lst.isSubList() {
        if lst.length == 0 {
            return false
        }
    } else {
        if lst.firstNode == nil {
            return false
        }
    }

    return list.AddAllAt(list.length, lst)

}

func (list *List) IsEmpty() bool {
    return list.length == 0 && list.firstNode == nil
}

func (list *List) AddAllAt(index int, lst *List) bool {

    if list.isSubList() {
        succ := list.parent.AddAllAt(list.startIndex+index, lst)
        list.length += lst.length
        list.endIndex = list.startIndex + list.length - 1
        return succ
    } else {

        //empty list
        if lst.firstNode == nil || index >= list.length || index < 0 {
            panic("Bad value for index or badly initialized list")
            return false
        }

        numNew := lst.length
        if numNew == 0 {
            return false
        }
        prev := new(Node)
        succ := new(Node)
        if index == list.length {
            succ = nil
            prev = list.lastNode
        } else {
            succ = list.getNode(index)
            prev = succ.prev
        }

        x := lst.firstNode

        for i := 0; i < numNew; i++ {
            e := x.val
            newNode := new(Node)
            newNode.initNode(prev, e, nil)
            if prev == nil {
                list.firstNode = newNode
            } else {
                prev.next = newNode
            }
            prev = newNode
            x = x.next
        }

        if succ == nil {
            list.lastNode = prev
        } else {
            prev.next = succ
            succ.prev = prev
        }

        list.length += numNew
        return true
    }
}

/**
 * Remove the first node that has
 * the same value as the parameter
 */
func (list *List) Remove(val interface{}) bool {

    if list.isSubList() {
        ind := list.IndexOf(val)
        if ind == -1 {
            return false
        } else {
            list.RemoveIndex(ind)

            list.length--
            list.endIndex--
            return true
        }

    } else {
        //empty list
        if list.firstNode == nil {
            return false
        }

        x := list.firstNode
        for i := 0; i < list.length; i++ {
            if x.val == val {
                succ := list.removeNode(x)

                if succ {
                    list.syncRemoval(i)
                }

                return succ
            }

            x = x.next
        }

        return false
    }

}

func (list *List) RemoveIndex(index int) bool {

    if list.isSubList() {
        return list.parent.RemoveIndex(index + list.startIndex)
    } else {

        x := list.firstNode
        for i := 0; i <= index; i++ {
            if index == i {
                succ := list.removeNode(x)

                if succ {
                    list.syncRemoval(index)
                }

                return succ
            }
            x = x.next

        }
        return false

    }

}

/**
 * Reflects changes in the parent list on the sublist when removals are made from the parent list
 */
func (list *List) syncRemoval(index int) {
    if list.subList != nil {

        if index <= list.subList.startIndex {
            list.subList.startIndex--
            list.subList.endIndex--
        } else if index > list.subList.startIndex && index <= list.subList.endIndex {
            list.subList.endIndex--
            list.subList.length--
        }

    }
}

/**
 * Reflects changes in the parent list on the sublist when additions are made to the parent list
 */
func (list *List) syncAdditions(index int) {
    if list.subList != nil {

        if index <= list.subList.startIndex {
            list.subList.startIndex++
            list.subList.endIndex++
        } else if index > list.subList.startIndex && index <= list.subList.endIndex {
            list.subList.endIndex++
            list.subList.length++
        }

    }
}

//Not backed
//Calling obj, Methodname, firstparam,  secondparam  return type
func (list *List) SubList(startIndex int, endIndex int) *List {

    if endIndex > list.length {
        panic(strconv.Itoa(endIndex) + " > " + strconv.Itoa(list.length) + " is not allowed")
    }

    if startIndex < 0 {
        panic(strconv.Itoa(startIndex) + " < 0 is not allowed")
    }
    if endIndex < 0 {
        panic(strconv.Itoa(endIndex) + " < 0 is not allowed")
    }
    if list.isSubList() {
        panic("Sublist Chaining not allowed. Sublists of sublists cannot be made")
    }

    /*
        parent := list
        for parent.isSubList() {
            startIndex += parent.startIndex
            endIndex += parent.startIndex
            parent = list.parent
        }
    */
    list.subList = new(List)
    list.subList.newList()
    list.subList.firstNode = nil
    list.subList.lastNode = nil
    list.subList.parent = list

    list.subList.length = endIndex - startIndex

    list.subList.startIndex = startIndex
    list.subList.endIndex = endIndex - 1

    return list.subList

}

func (list *List) isSubList() bool {
    return list.parent != nil
}

/**
 * Returns the (non-nil) Node at the specified element index.
 */
func (list *List) getNode(index int) *Node {
    if index < 0 {
        panic("Index=(" + strconv.Itoa(index) + ") < 0 is not allowed")
    }

    if index > list.length {
        panic("Index=(" + strconv.Itoa(index) + ") > list-length=(" + strconv.Itoa(list.length) + ") is not allowed")
    }

    if list.isSubList() {
        return list.parent.getNode(list.startIndex + index)
    }

    // NOTE x >> y is same as x ÷ 2^y
    if index < (list.length >> 1) {
        x := list.firstNode
        for i := 0; i < index; i++ {
            x = x.next
        }
        return x
    } else {
        x := list.lastNode
        for i := list.length - 1; i > index; i-- {
            x = x.prev
        }
        return x
    }
}

/**
 * Returns the (non-nil) Node at the specified element index.
 */
func (list *List) getBoundaryNodes() (*Node, *Node) {

    if list.isSubList() {

        start := list.startIndex
        end := list.endIndex

        first := list.getNode(0)
        last := new(Node)

        x := first

        i := start

        if list.length > list.parent.length-list.endIndex {

            last = list.getLastNode()

        } else {
            for ; i < end; i++ {
                x = x.next
            }
        }
        last = x
        return first, last
    } else {
        return list.firstNode, list.lastNode
    }

}

func (list *List) Get(index int) interface{} {

    return list.getNode(index).val

}

func (list *List) getLastNode() *Node {
    if list.isSubList() {
        return list.parent.getNode(list.endIndex)
    } else {
        return list.lastNode
    }
}

func (list *List) LastElement() interface{} {
    return list.getLastNode().val
}

func (list *List) IndexOf(val interface{}) int {

    if list.isSubList() {
        startNode := list.getNode(0)

        i := 0
        for x := startNode; i < list.length; x = x.next {

            if val == x.val {
                return i
            }
            i++
        }
        return -1

    } else {

        x := list.firstNode

        if x.val == val {
            return 0
        }

        for i := 0; i < list.length; i++ {

            if val == x.val {
                return i
            }

            x = x.next
        }

        return -1
    }

}
func (list *List) indexOfNode(node *Node) int {

    if list.isSubList() {
        startNode := list.getNode(0)

        i := 0
        for x := startNode; i < list.length; x = x.next {

            if node == x {
                return i
            }
            i++
        }
        return -1

    } else {

        x := list.firstNode

        if x == node {
            return 0
        }

        for i := 0; i < list.length; i++ {

            if node == x {
                return i
            }

            x = x.next
        }

        return -1
    }

}
func (list *List) Contains(val interface{}) bool {
    return list.IndexOf(val) != -1

}
func (list *List) containsNode(node *Node) bool {
    return list.indexOfNode(node) != -1

}

/**
 * Links val as first element.
 */
func (list *List) prepend(val interface{}) {
    f := list.firstNode
    newNode := new(Node)
    newNode.initNode(nil, val, f)
    list.firstNode = newNode
    if f == nil {
        list.lastNode = newNode
    } else {
        f.prev = newNode
    }
    list.length++
}

/**
 * Links val as last element.
 */
func (list *List) append(val interface{}) {
    l := list.lastNode
    newNode := new(Node)
    newNode.initNode(l, val, nil)
    list.lastNode = newNode
    if l == nil {
        list.firstNode = newNode
    } else {
        l.next = newNode
    }
    list.length++
}

/**
 * Inserts element e before non-null Node succ.
 * ONLY TO BE CALLED BY BASE PARENT LISTS
 * Return a pointer to the new node that was inserted.
 * This will help with spontaneous insertions
 */
func (list *List) insertBefore(e interface{}, succ *Node) *Node {

    prev := succ.prev

    newNode := new(Node)
    newNode.initNode(prev, e, succ)

    succ.prev = newNode
    if prev == nil {
        list.firstNode = newNode
    } else {
        prev.next = newNode
    }
    list.length++
    return newNode
}

/**
 * Inserts element e after non-null Node succ.
 *
 * ONLY TO BE CALLED BY BASE PARENT LISTS
 * Return a pointer to the new node that was inserted.
 * This will help with spontaneous insertions
 */
func (list *List) insertAfter(e interface{}, succ *Node) *Node {

    next := succ.next

    newNode := new(Node)
    newNode.initNode(succ, e, succ.next)

    succ.next = newNode
    if next == nil {
        list.lastNode = newNode
    } else {
        next.prev = newNode
    }
    list.length++

    return newNode
}
func (list *List) Clear() {

    if list.isSubList() {

        begin, end := list.getBoundaryNodes()

        //The node just before this sublist's first node
        leftBound := begin.prev

        //The node just after this range's last node
        rightBound := end.next

        if leftBound != nil {
            leftBound.next = rightBound
        } else {
            list.parent.firstNode = rightBound
        }

        if rightBound != nil {
            rightBound.prev = leftBound
        } else {
            list.parent.lastNode = leftBound
        }

        list.removeLinkedRange(begin, end)

        list.parent.length -= list.length
        list.endIndex = list.startIndex
        list.length = 0

    } else {
        x := list.firstNode

        for x != nil {
            next := x.next
            x.val = nil
            x.next = nil
            x.prev = nil
            x = next
        }
        list.firstNode = nil
        list.lastNode = nil
        list.length = 0

        if list.subList != nil {
            list.subList.startIndex = 0
            list.subList.endIndex = 0
            list.subList.length = 0
        }

    }

}
func (list *List) removeLinkedRange(startNode *Node, stopNode *Node) {

    for x := startNode; x != stopNode; x = x.next {

        x.val = nil
        if x != startNode {
            x.prev = nil
        }

    }

}
func (list *List) Log(optionalLabel string) {

    if list.isSubList() {

        if list.length == 0 {
            fmt.Println(optionalLabel, ":\n[], len: 0")
            return
        }

        appender := optionalLabel + ":\n ["

        i := 0

        for x := list.getNode(i); i < list.length; x = x.next {
            dType := reflect.TypeOf(x.val).Kind()
            if dType == reflect.String {
                appender += x.val.(string) + ","
            } else if dType == reflect.Int {
                appender += strconv.Itoa(int(x.val.(int))) + ","
            } else if dType == reflect.Int8 {
                appender += strconv.Itoa(int(x.val.(int8))) + ","
            } else if dType == reflect.Int16 {
                appender += strconv.Itoa(int(x.val.(int16))) + ","
            } else if dType == reflect.Int32 {
                appender += strconv.Itoa(int(x.val.(int32))) + ","
            } else if dType == reflect.Int64 {
                appender += strconv.Itoa(int(x.val.(int64))) + ","
            }

            i++
        }
        appender += "], len: " + strconv.Itoa(list.length) + ", startIndex: " + strconv.Itoa(list.startIndex) + ", endIndex: " + strconv.Itoa(list.endIndex)
        fmt.Println(appender)

    } else {

        if list.firstNode == nil {
            fmt.Println(optionalLabel + ":\n[], len: 0")
            return
        }
        counter := 0
        currentNode := list.firstNode
        dType := reflect.TypeOf(currentNode.val).Kind()

        appender := optionalLabel + ":\n"
        if dType == reflect.String {
            appender += "[" + currentNode.val.(string) + ","
        } else if dType == reflect.Int {
            appender += "[" + strconv.Itoa(currentNode.val.(int)) + ","
        } else if dType == reflect.Int8 {
            appender += "[" + strconv.Itoa(int(currentNode.val.(int8))) + ","
        } else if dType == reflect.Int16 {
            appender += "[" + strconv.Itoa(int(currentNode.val.(int16))) + ","
        } else if dType == reflect.Int32 {
            appender += "[" + strconv.Itoa(int(currentNode.val.(int32))) + ","
        } else if dType == reflect.Int64 {
            appender += "[" + strconv.Itoa(int(currentNode.val.(int64))) + ","
        }

        for currentNode.next != nil && counter < list.length {
            dType = reflect.TypeOf(currentNode.next.val).Kind()
            if dType == reflect.String {
                appender += currentNode.next.val.(string) + ","
            } else if dType == reflect.Int {
                appender += strconv.Itoa(int(currentNode.next.val.(int))) + ","
            } else if dType == reflect.Int8 {
                appender += strconv.Itoa(int(currentNode.next.val.(int8))) + ","
            } else if dType == reflect.Int16 {
                appender += strconv.Itoa(int(currentNode.next.val.(int16))) + ","
            } else if dType == reflect.Int32 {
                appender += strconv.Itoa(int(currentNode.next.val.(int32))) + ","
            } else if dType == reflect.Int64 {
                appender += strconv.Itoa(int(currentNode.next.val.(int64))) + ","
            }

            currentNode = currentNode.next
            counter++
        }
        appender += "], len: " + strconv.Itoa(list.length)
        fmt.Println(appender)

    }

}

ByteArrayBuilder: A simplfied version of java.nio.ByteBuffer

I was doing some work in video streaming from mobile phones to PC recently and I was dealing with a lot of byte array streams from client to...