You can create maps using value by alpha using SLD - (the point being that WA has a lower unemployment rate than OR but has more people so it appears more solid).

The trick is to use an expression in the fill-opacity element. If you add the SLD file below to a standard GeoServer install you can see the topp:states layer rendered.
In GeoTools it is even easier as you can use any function you like to set the fill opacity.
<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml"
xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd">
<NamedLayer>
<Name>USA states Unemployment</Name>
<UserStyle>
<Name>Unemployment</Name>
<Title>Unemploymentin the United States</Title>
<Abstract>A sample filter that filters the United States into three
categories of unemployment, drawn in different colors</Abstract>
<FeatureTypeStyle>
<Rule>
<Title>< 5%</Title>
<ogc:Filter>
<ogc:PropertyIsLessThan>
<ogc:Mul>
<ogc:Div>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
<ogc:Add>
<ogc:PropertyName>EMPLOYED</ogc:PropertyName>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
</ogc:Add>
</ogc:Div>
<ogc:Literal>100</ogc:Literal>
</ogc:Mul>
<ogc:Literal>5</ogc:Literal>
</ogc:PropertyIsLessThan>
</ogc:Filter>
<PolygonSymbolizer>
<Stroke>
<CssParameter name="stroke-width">0.2</CssParameter>
</Stroke>
<Fill>
<!-- CssParameters allowed are fill (the color) and fill-opacity -->
<CssParameter name="fill">#4DFF4D</CssParameter>
<CssParameter name="fill-opacity">
<ogc:Div>
<ogc:PropertyName>PERSONS</ogc:PropertyName>
<ogc:Literal>30e6</ogc:Literal>
</ogc:Div>
</CssParameter>
</Fill>
</PolygonSymbolizer>
<TextSymbolizer>
<Label>
<ogc:PropertyName>STATE_ABBR</ogc:PropertyName>
<![CDATA[
]]>
<ogc:Function name="numberFormat">
<ogc:Literal>#.##</ogc:Literal>
<ogc:Mul>
<ogc:Div>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
<ogc:Add>
<ogc:PropertyName>EMPLOYED</ogc:PropertyName>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
</ogc:Add>
</ogc:Div>
<ogc:Literal>100</ogc:Literal>
</ogc:Mul>
</ogc:Function>
</Label>
<Font>
<CssParameter name="font-family">Times New Roman</CssParameter>
<CssParameter name="font-style">Normal</CssParameter>
<CssParameter name="font-size">14</CssParameter>
</Font>
<LabelPlacement>
<PointPlacement>
<AnchorPoint>
<AnchorPointX>0.5</AnchorPointX>
<AnchorPointY>0.5</AnchorPointY>
</AnchorPoint>
</PointPlacement>
</LabelPlacement>
</TextSymbolizer>
</Rule>
<Rule>
<Title>5-7%</Title>
<ogc:Filter>
<ogc:PropertyIsBetween>
<ogc:Mul>
<ogc:Div>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
<ogc:Add>
<ogc:PropertyName>EMPLOYED</ogc:PropertyName>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
</ogc:Add>
</ogc:Div>
<ogc:Literal>100</ogc:Literal>
</ogc:Mul>
<ogc:LowerBoundary>
<ogc:Literal>5</ogc:Literal>
</ogc:LowerBoundary>
<ogc:UpperBoundary>
<ogc:Literal>7</ogc:Literal>
</ogc:UpperBoundary>
</ogc:PropertyIsBetween>
</ogc:Filter>
<PolygonSymbolizer>
<Stroke>
<CssParameter name="stroke-width">0.2</CssParameter>
</Stroke>
<Fill>
<!-- CssParameters allowed are fill (the color) and fill-opacity -->
<CssParameter name="fill">#FF4D4D</CssParameter>
<CssParameter name="fill-opacity">
<ogc:Div>
<ogc:PropertyName>PERSONS</ogc:PropertyName>
<ogc:Literal>30e6</ogc:Literal>
</ogc:Div>
</CssParameter>
</Fill>
</PolygonSymbolizer>
<TextSymbolizer>
<Label>
<ogc:PropertyName>STATE_ABBR</ogc:PropertyName>
<![CDATA[
]]>
<ogc:Function name="numberFormat">
<ogc:Literal>#.##</ogc:Literal>
<ogc:Mul>
<ogc:Div>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
<ogc:Add>
<ogc:PropertyName>EMPLOYED</ogc:PropertyName>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
</ogc:Add>
</ogc:Div>
<ogc:Literal>100</ogc:Literal>
</ogc:Mul>
</ogc:Function>
</Label>
<Font>
<CssParameter name="font-family">Times New Roman</CssParameter>
<CssParameter name="font-style">Normal</CssParameter>
<CssParameter name="font-size">14</CssParameter>
</Font>
<LabelPlacement>
<PointPlacement>
<AnchorPoint>
<AnchorPointX>0.5</AnchorPointX>
<AnchorPointY>0.5</AnchorPointY>
</AnchorPoint>
</PointPlacement>
</LabelPlacement>
</TextSymbolizer>
</Rule>
<Rule>
<Title>> 7%</Title>
<!-- like a linesymbolizer but with a fill too -->
<ogc:Filter>
<ogc:PropertyIsGreaterThan>
<ogc:Mul>
<ogc:Div>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
<ogc:Add>
<ogc:PropertyName>EMPLOYED</ogc:PropertyName>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
</ogc:Add>
</ogc:Div>
<ogc:Literal>100</ogc:Literal>
</ogc:Mul>
<ogc:Literal>7</ogc:Literal>
</ogc:PropertyIsGreaterThan>
</ogc:Filter>
<PolygonSymbolizer>
<Stroke>
<CssParameter name="stroke-width">0.2</CssParameter>
</Stroke>
<Fill>
<!-- CssParameters allowed are fill (the color) and fill-opacity -->
<CssParameter name="fill">#4D4DFF</CssParameter>
<CssParameter name="fill-opacity">
<ogc:Div>
<ogc:PropertyName>PERSONS</ogc:PropertyName>
<ogc:Literal>30e6</ogc:Literal>
</ogc:Div>
</CssParameter>
</Fill>
</PolygonSymbolizer>
<TextSymbolizer>
<Label>
<ogc:PropertyName>STATE_ABBR</ogc:PropertyName>
<![CDATA[
]]>
<ogc:Function name="numberFormat">
<ogc:Literal>#.##</ogc:Literal>
<ogc:Mul>
<ogc:Div>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
<ogc:Add>
<ogc:PropertyName>EMPLOYED</ogc:PropertyName>
<ogc:PropertyName>UNEMPLOY</ogc:PropertyName>
</ogc:Add>
</ogc:Div>
<ogc:Literal>100</ogc:Literal>
</ogc:Mul>
</ogc:Function>
</Label>
<Font>
<CssParameter name="font-family">Times New Roman</CssParameter>
<CssParameter name="font-style">Normal</CssParameter>
<CssParameter name="font-size">14</CssParameter>
</Font>
<LabelPlacement>
<PointPlacement>
<AnchorPoint>
<AnchorPointX>0.5</AnchorPointX>
<AnchorPointY>0.5</AnchorPointY>
</AnchorPoint>
</PointPlacement>
</LabelPlacement>
</TextSymbolizer>
</Rule>
<Rule>
<Title>Boundary</Title>
<LineSymbolizer>
</LineSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>