Why this code was written this way instead of just checking against the ID by linearly iterating over the Components, I have no idea.
There's another comment here that shows their JPEG decoder only supports 1 or 3 components. Using a hash table for at most 3 entries is astronomical overkill! The field for the number of components in a JPEG file is only a byte - so even if you were to support more than 3 components, it would be 255 at most, and sane JPEG files are unlikely to have more than 4 in practice. So fixed-size arrays are the perfect solution. I have a very good idea why it was written like that, however: the mere availability and ease of use of abstract data structures naturally leads to their overuse by what seems to be an overwhelming majority of developers, and the eagerness to "futureproof" and add unnecessary complexity is also very common.
Overcomplexity creates bugs, and (leaky) abstractions hide them. Even if the complexity (and bug) isn't visible in your code, it's still there. If the initial code had been reviewed by me, it most certainly would not pass.
I am saying this as someone who has actually written a JPEG decoder --- it is not as difficult as it may sound, and I highly recommend giving it a try --- and also witnessed (and fixed) the messes that people get in with overcomplicating things. Perhaps that slight "architecture astronaut" mentality comes from starting with a higher-level language; I started with Asm and my preferred language is usually C, and I haven't seen the tendency to overcomplicate much in others who did the same.
The reason the Components were in a hash table was that they would then be checked against the component ordering in a “Start of Scan” section to make sure all the components in the SOS section are in the expected order.
For comparison, this is the corresponding code in my JPEG decoder. I didn't even bother using a loop:
if(read_byte()!= cids[0])
data_error("SOS scan first component must match");
hts[0] = read_byte(); /* high nybble: DC table index; low nybble: AC table index */
if(read_byte() != cids[1])
data_error("SOS scan second component must match");
hts[1] = read_byte();
if(read_byte() != cids[2])
data_error("SOS scan third component must match");
hts[2] = read_byte();