Toon posts:

[Java] Arraylist uit database sorteren op veld

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik haal uit een database een lijst met gebruikers op.
Dat doe ik d.m.v. een select statement en de result set daarvan in een arraylist te hangen.
Vervolgens laat ik de resultaten op een jsp pagina zien.
Echter komt de volgorde er niet naar mijn wens uit. Alles staat in de volgorde zoals het in de database is ingevuld.
Graag zou ik het willen sorteren op achternaam.

Nu kan ik uiteraard het select statement aanpassen door er een order by in te voegen, echter is dat niet wenselijk.
Is het ook mogelijk om die arraylist te storten op een veldnaam uit de database?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package nl.intranet.action;

import java.sql.*;
import java.util.*;
import javax.servlet.http.*;

import nl.intranet.dto.*;
import nl.intranet.util.*;

public class PhotolistAction implements Action
{
    private Statement stmt = null;

    public PhotolistAction() throws Exception
    {
        Connection connection = ConnectionCache.getConnection("java:/comp/env/jdbc/intranetds");
        stmt = connection.createStatement();
    }

    public String execute(HttpServletRequest request, HttpServletResponse response) throws SQLException
    {
        HttpSession session = request.getSession();

        // Set active tab
        session.setAttribute("tab", "photobook");

        // Fetch photobook data
        Enumeration allParameters = request.getParameterNames();
        String sql = "select * from users";
        boolean firstParameter = true;

        while (allParameters.hasMoreElements())
        {
            String name = (String) allParameters.nextElement();
            String value = request.getParameter(name);

            if (!name.equals("action") && ! (value == null || value.equals("")))
            {
                if (firstParameter)
                {
                    sql += " where " + name + " = '" + value + "'";

                    firstParameter = false;
                }
                else
                {
                    sql += " and " + name + " = '" + value + "'";
                }
            }
        }

        ResultSet rs = stmt.executeQuery(sql);
        ArrayList users = DTOFactory.createUsers(rs);
        rs.close();

        // Store acquired data in session
        session.setAttribute("photolist", users);

        return "/photolist.jsp";
    }
}

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 11:49

gorgi_19

Kruimeltjes zijn weer op :9

Nu kan ik uiteraard het select statement aanpassen door er een order by in te voegen, echter is dat niet wenselijk.
Is het ook mogelijk om die arraylist te storten op een veldnaam uit de database?
Waarom is dat niet wenselijk, eigenlijk? :)

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Topicstarter
Dan kan ik in het URL niet meer een variable mee geven.
Bijv: http://intranet/dispatcher?action=photolist&office=Amsterdam

&office=Amsterdam

Werkt dan niet meer.
Ik krijg dan een syntax error.
Toen ik de order by weg haalde kreeg ik die niet.

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 20-05 20:29

Robtimus

me Robtimus no like you

Collections.sort(List list, Comparator c)
De list wordt gesorteerd, waarbij de Comparator voor de volgorde zorgt. Die moet je wel eventjes zelf schrijven, of de objecten in je list de Comparable interface laten implementeren, dan kan die Comparator in de sort weggelaten worden.

edit:
Waarom deed die link het niet goed? Dan maar zo:
Collections, zelf even de goede sort kiezen.

[ Voor 36% gewijzigd door Robtimus op 19-10-2004 13:25 ]

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • nxt
  • Registratie: November 2001
  • Laatst online: 04-02 09:36

nxt

Verwijderd schreef op 19 oktober 2004 @ 13:13:
Dan kan ik in het URL niet meer een variable mee geven.
Bijv: http://intranet/dispatcher?action=photolist&office=Amsterdam

&office=Amsterdam

Werkt dan niet meer.
Ik krijg dan een syntax error.
Toen ik de order by weg haalde kreeg ik die niet.
die syntax error is omdat je sql query dan niet meer klopt
een ORDER BY komt altijd na de where clause en omdat je alle parameters behalve action in de where clause stopt, zul je daar een oplossing voor moeten verzinnen.
Momenteel kijk je al of de naam van de parameter 'action' is slaat deze over bij het genereren van de where.
Voor de order by zou je net zoiets kunnen doen. Dus bijvoorbeeld een aparte (optionele?) parameter genaamd 'orderby' o.i.d. en deze na de while lus nog aan de query toevoegen.

offtopic:
ik zie dat je strings aan elkaar plakt met +, dit is zeker als het verspreid staat over meerdere statements vrij inefficient. Je kunt beter een StringBuffer of StringBuilder instantieren en daar de strings aan toevoegen met de append method, en als je dan klaar bent met de toString() method de StringBuffer/StringBuilder weer omzetten naar een string.

  • zneek
  • Registratie: Augustus 2001
  • Laatst online: 08-02-2025
Ik zou zeggen, lees de SQL handleiding over hoe ORDER BY te gebruiken, of volg de links naar de Collections documentatie.

Eventueel kun je ook naar Hibernate kijken. Een O/R mapper die zo'n beetje alles wat je kunt bedenken op persistentie gebied voor je kan regelen. Gebruik je Eclipse? Helemaal mooi, dan moet je HibernateSynchroniser erbij pakken, scheelt een boel ge-emmer.

Verwijderd

Als je dan toch progmatisch je list wil gaan sorteren wees dan wel zo handig om een linkedlist implementatie te nemen in plaats van een arraylist.

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Verwijderd schreef op 20 oktober 2004 @ 02:26:
Als je dan toch progmatisch je list wil gaan sorteren wees dan wel zo handig om een linkedlist implementatie te nemen in plaats van een arraylist.
Waarom? Het wisselen van twee posities (waarop mergesort/quicksort op gebaseerd zijn) zijn even snel in een LinkedList als in een ArrayList nl O(1). Om precies te zijn is een ArrayList zelfs sneller dan een LinkedList, zie Collections.sort() hier:

Java:
1
2
3
4
5
6
7
8
9
public static void sort(List list, Comparator c) {
    Object a[] = list.toArray();
    Arrays.sort(a, c);
    ListIterator i = list.listIterator();
    for (int j=0; j<a.length; j++) {
        i.next();
        i.set(a[j]);
    }
}

Het sorteren gebeurt gewoon op array's en een toArray() van een ArrayList gaat vlotter dan een toArray() van LinkedList (O(1) tov O(n)). Niet dat dat veel uitmaakt met de O(n^2) max sorting tijd van quicksort, maarja ;)

[edit] Trouwens ik bedenk me net dat Radix Sort hier ook een optie kan zijn. Echter, dan maakt het nog niet veel uit omdat je dan de lijst ook per 1 moet aflopen

[edit2]
Uhm ik praat onzin. Ook toArray van een ArrayList gaat in O(n) tijd omdat hij geen reference teruggeeft maar een arrayCopy() doet. Sorry. Het sorteren van en LinkedList en een ArrayList met Collections.sort() gaat dus even snel.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
public Object[] toArray(Object a[]) {
        if (a.length < size)
            a = (Object[])java.lang.reflect.Array.newInstance(
                                a.getClass().getComponentType(), size);

    System.arraycopy(elementData, 0, a, 0, size);

        if (a.length > size)
            a[size] = null;

        return a;
}

[ Voor 33% gewijzigd door Glimi op 20-10-2004 08:49 ]


Verwijderd

nxt schreef op 20 oktober 2004 @ 00:07:
[...]
offtopic:
ik zie dat je strings aan elkaar plakt met +, dit is zeker als het verspreid staat over meerdere statements vrij inefficient. Je kunt beter een StringBuffer of StringBuilder instantieren en daar de strings aan toevoegen met de append method, en als je dan klaar bent met de toString() method de StringBuffer/StringBuilder weer omzetten naar een string.
offtopic:
Volgens de java-api worden plusjes gewoon gecompiled naar StringBuffer. De StringBuffer gebruiken is dan dus alleen maar extra werk. Het wordt uiteindelijk precies hetzelfde gecompiled.


edit:
Ah, op die manier. Thnx voor de uitleg Glimi :)

[ Voor 5% gewijzigd door Verwijderd op 20-10-2004 09:40 ]


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Verwijderd schreef op 20 oktober 2004 @ 09:17:
offtopic:
Volgens de java-api worden plusjes gewoon gecompiled naar StringBuffer. De StringBuffer gebruiken is dan dus alleen maar extra werk. Het wordt uiteindelijk precies hetzelfde gecompiled.
Nee het is precies dit verschil:
Met +=
Java:
1
2
3
String a = "Example";
for( int i =0; i < 1000; ++i)
   a = new StringBuffer( a ).append( " add This " ).toString();


Tov van een StringBuffer in je code
Java:
1
2
3
StringBuffer a = "Example";
for( int i =0; i < 1000; ++i)
   a.append( "addThis" );

Het scheelt je dus een hoop tijd bij de creatie van objecten welke niet nodig zijn. Ik zal trouwens even kijken of de huidige 1.5 dit niet anders doet.

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Testje uitgevoerd mbt de String concatenatie op de 1.5.0 final.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import java.util.Arrays;

public class TestString {

    private static final String START_STRING    = "Example";
    private static final String APPEND_STRING   = " add This ";
    private static final int    ITERATIONS      = 1000;
    private static final int SUITE_ITERATIONS   = 1000;

    private int _iterations;

    public static void main( String[] args ) {

        TestString test = new TestString( ITERATIONS );
        test.run();
    }

    public TestString( final int p_iterations ) {

        _iterations = p_iterations;
    }

    public void run( ) {

        long[] l_stringTimes  = new long[ SUITE_ITERATIONS ];
        long[] l_bufferTimes  = new long[ SUITE_ITERATIONS ];

        for( int i = 0; i < SUITE_ITERATIONS; ++i ) {

            if( i%2 == 0) {

                l_stringTimes[i] = testString( _iterations );
                l_bufferTimes[i] = testBuffer( _iterations );
            } else {

                l_bufferTimes[i] = testBuffer( _iterations );
                l_stringTimes[i] = testString( _iterations );
            }

            if( i%100 == 0 ) {
                System.out.println( "" + i/10 + "%");
            }
        }

        Arrays.sort( l_stringTimes );
        Arrays.sort( l_bufferTimes );

        long l_avgStringTimes   = average( l_stringTimes );
        long l_avgBufferTimes   = average( l_bufferTimes );

        System.out.println( "Name     | Min Time | Max Time | Avg Time");
        System.out.println( "Strings  | "
                            + l_stringTimes[0] + " | "
                            + l_stringTimes[ SUITE_ITERATIONS - 1 ] + " | "
                            + l_avgStringTimes );

        System.out.println( "Buffer  | "
                            + l_bufferTimes[0] + " | "
                            + l_bufferTimes[ SUITE_ITERATIONS - 1 ] + " | "
                            + l_avgBufferTimes );

    }

    public long testString( final int p_iterations ) {

        long l_start  = System.currentTimeMillis();
        String l_string = START_STRING;

        for( int i = 0; i < p_iterations; ++i )
            l_string += APPEND_STRING;

        return System.currentTimeMillis() - l_start;
    }

    public long testBuffer( final int p_iterations ) {

        long l_start  = System.currentTimeMillis();
        StringBuffer l_buffer    = new StringBuffer( START_STRING );

        for( int i = 0; i < p_iterations; ++i)
            l_buffer.append( APPEND_STRING );

        return System.currentTimeMillis() - l_start;
    }

    private long average( final long[] l_array ) {

        long l_return = 0;

        for( int i = 0; i < l_array.length; ++i )
            l_return += l_array[i];

        return l_return/l_array.length;
    }
}
Op de code is heel wat aan te merken, maar het resultaat geeft wel voldoende aan hoe het zit met de traagheid van Strings plakken:

code:
1
2
3
Name     | Min Time | Max Time | Avg Time
Strings  | 82 | 1217 | 102
Buffer   | 0 | 2 | 0


[edit] Die extreem lelijke percentage teller heb ik er maar ingezet omdat hij toch wel echt berelang bezig was :P M'n eerste poging was ook op 100.000 iteraties per test, maar dat duurde me toch wat te lang :P

[ Voor 6% gewijzigd door Glimi op 20-10-2004 10:21 ]


  • momania
  • Registratie: Mei 2000
  • Laatst online: 06:42

momania

iPhone 30! Bam!

Glimi schreef op 20 oktober 2004 @ 10:18:
Testje uitgevoerd mbt de String concatenatie op de 1.5.0 final.
In 1.5 heb je nu de StringBuilder. Dat is een snellere variant van de StringBuffer :Y)

Laatst nog een topic over geweest..

[edit]
Deze dus: [rml][ JAVA] StringBuilder benchmarks[/rml]

[ Voor 12% gewijzigd door momania op 20-10-2004 11:35 ]

Neem je whisky mee, is het te weinig... *zucht*


Verwijderd

Topicstarter
't kan nog simpeler:

sql += " order by lastname";

In de regel boven de ResultSet zetten en klaar. :)

  • jAnO!
  • Registratie: Januari 2002
  • Laatst online: 01-05 18:22

jAnO!

lalalavanillevla

Verwijderd schreef op 25 oktober 2004 @ 10:18:
't kan nog simpeler:

sql += " order by lastname";

In de regel boven de ResultSet zetten en klaar. :)
ja en dat is wat je vorige week woensdag al verteld is ... ;-)
nxt schreef op 20 oktober 2004 @ 00:07:
Dus bijvoorbeeld een aparte (optionele?) parameter genaamd 'orderby' o.i.d. en deze na de while lus nog aan de query toevoegen.

When some people work at a place for ten years they get ten years of experience, other people work at a place for ten years and get one year of experience ten times.

Pagina: 1